Compare commits

...
Sign in to create a new pull request.

49 commits

Author SHA1 Message Date
c9c6b4863d draw filled boxes for petri net example/tutorial 2025-07-23 16:56:52 +02:00
ccf075e2e7 newline 2025-07-23 16:35:40 +02:00
7974b1a26d add API LaTeX table 2025-07-23 16:24:24 +02:00
7eca6ddda4 update readme 2025-07-23 16:04:28 +02:00
7172ade9fa update readme 2025-07-23 16:01:52 +02:00
0b936a48d1 get rid of outdated examples 2025-07-23 16:00:42 +02:00
4ba0ed09b2 Merge with Robbe's scheduling language 2025-07-23 15:30:32 +02:00
457aac48b3 fix 2025-07-23 15:15:17 +02:00
6b5931343d Merge remote-tracking branch 'github/master' into development 2025-07-23 13:59:00 +02:00
558772fbe4 commit some long outstanding changes 2025-07-23 13:57:25 +02:00
e046f2f972 nice visualization 2025-07-23 13:56:16 +02:00
fecce51828 add tutorial on model transformation with pivots 2025-07-23 13:41:28 +02:00
790ba031cf add conformance check to MT tutorial 2025-07-23 11:06:32 +02:00
33a70c9a88 add model transformation tutorial 2025-07-23 11:03:48 +02:00
66b9a2dc33 add tutorial 2025-07-23 10:04:08 +02:00
35f74aed84 get rid of unnecessary link 2025-07-22 17:16:11 +02:00
069cb439cb add two more tutorials 2025-07-22 17:15:00 +02:00
1dfeef767e start writing tutorials 2025-07-22 16:47:46 +02:00
robbe
e1eb6e0df4 Placeholders for node documentation (what and how)
what and why covered in transformation/schedule/doc/schedule.md
2025-06-30 18:22:16 +02:00
robbe
af12f3d524 Added some documentation, fixed test and missing schedule 2025-06-30 18:03:47 +02:00
robbe
fd6c8b4277 Added some documentation, fixed test and missing schedule 2025-06-30 18:03:24 +02:00
robbe
ebfd85a666 A fully working version of the scheduling language with added examples 2025-06-27 12:21:41 +02:00
robbe
ec42f74960 Added an eval_context_decorator to allow user defined functions in rules 2025-06-27 12:20:00 +02:00
robbe
e4ea9a0410 Added ';' required after a global constraint for concistency 2025-06-27 12:17:27 +02:00
robbe
58366fa9bb add Action code to the cd parser. 2025-06-27 12:17:10 +02:00
robbe
9eea3618d0 cleanup the od api interface 2025-06-27 12:15:19 +02:00
joeriexelmans
35f74ab79d
Merge pull request #2 from joeriexelmans/development
Adding bytes as a type + add FTG+PM++ formalism
2025-06-24 13:59:45 +02:00
Inte Vleminckx
9475b1fdc5 Merge remote-tracking branch 'origin/master' into development
# Conflicts:
#	api/od.py
2025-06-03 16:25:24 +02:00
Inte Vleminckx
d00b9c25db Add 'simplified' version of the FTG+PM++ formalism with operational semantics 2025-06-03 16:17:37 +02:00
robbe
04a17f6ac8 has_slot(obj) now works on instance ipv class. Useful for optional field 2025-04-24 13:07:32 +02:00
robbe
8ee9fba4ea petrinet example fixed 2025-04-24 12:33:38 +02:00
robbe
756b3f30da get_slots and is_instance added to readonly api + is_instance implementation 2025-04-24 12:27:28 +02:00
robbe
5e5865d0d5 base_case of len == 0 added (same as Interactive decisionMaker) 2025-04-24 12:25:44 +02:00
robbe
bad9e8e32a removed unused variable 2025-04-24 12:24:51 +02:00
robbe
87fc7362db Scheduler petrinet example 2025-04-24 12:23:29 +02:00
robbe
2c64ebda67 Scheduler first commit 2025-04-24 12:23:07 +02:00
Inte Vleminckx
ced3edbd08 fix bytes extraction + give created objects also a name when None is provided (same as links) 2025-02-19 10:45:46 +01:00
07edcc0a8e Merge remote-tracking branch 'github/development' into development 2025-02-05 16:27:01 +01:00
a95a99f722 Merge remote-tracking branch 'github/development' into development 2025-02-05 16:26:37 +01:00
Inte Vleminckx
51b8bdb001 Add test for bytes type 2025-02-05 16:26:30 +01:00
e0136937b9 cleanup 2025-02-05 16:26:22 +01:00
Inte Vleminckx
98f36c4cf0 Adding bytes as a type 2025-02-05 16:24:22 +01:00
Inte Vleminckx
86cd7027f3 Adding bytes as a type 2025-02-05 16:01:56 +01:00
6c41c83f4f rename branch 2025-02-05 10:40:40 +01:00
ad6fcd7a24 add type check when overwriting slot value 2025-01-29 16:16:59 +01:00
a245d0a406 add a todo thingy 2025-01-29 16:16:47 +01:00
ecf669425f update readme 2025-01-27 17:07:36 +01:00
0ed716585c update readme 2025-01-27 16:58:13 +01:00
8fe7b0ea04 Commit some outstanding changes. Add TODO for cleanup. 2025-01-27 16:03:45 +01:00
229 changed files with 10805 additions and 3370 deletions

View file

@ -13,6 +13,7 @@ Features:
- Class Diagrams (self-conforming)
- Causal Block Diagrams language
- Petri Net language
- [Repotting the Geraniums](https://ris.utwente.nl/ws/portalfiles/portal/5312315/gtvmt2009.pdf)
## Dependencies
@ -26,7 +27,10 @@ Features:
The following branches exist:
* `mde2425` - the branch containing a snapshot of the repo used for the MDE assignments 24-25. No breaking changes will be pushed here. After the re-exams (Sep 2025), this branch will be frozen.
* `master` - currently equivalent to `mde2425` (this is the branch that was cloned by the students). This branch will be deleted after Sep 2025, because the name is too vague.
* `development` - in this branch, new development will occur, primarily cleaning up the code to prepare for next year's MDE classes.
* `mde2425` - contains a snapshot of the repo used for the MDE assignments 24-25. This branch should remain frozen.
## Tutorial
A good place to learn how to use muMLE is the `tutorial` directory. Each file is an executable Python script that explains muMLE step-by-step (read the comments).

46
TODO.txt Normal file
View file

@ -0,0 +1,46 @@
Things that need to be cleaned up:
- At several places in the code, it is assumed that from the root node, there is an edge labeled 'SCD' containing the self-conforming meta-meta-model. It would be better for parts of the code that need the meta-meta-model to receive this model as a (function) parameter.
- The whole 'ModelRef'-construct does not work as originally foreseen. It is currently only used for attributes of primitive types, where it unnecessarily complicates things. Better to get rid of it.
Known bugs:
- Cannot parse negative numbers
- When merging models, the model element names must not overlap. Maybe allow some kind of prefixing of the overlapping names? Difficulty porting existing models to the merged models if the type names have changed...
Merging (meta-)models is a nightmare:
- Prefixing the type names (to avoid naming collisions) is not an option:
(*) constraints (and transformation rules) already contain API calls that mention type names -> all of these would break
(*) don't want to prefix primitive types like "Integer", "String", ... because the existing code already assumes these exact names
- Not prefixing the type names leads to naming collisions, even if names are carefully chosen:
(*) anonymous names, e.g., Inheritance-links still result in naming collisions (requiring auto-renaming?)
Feature requests:
- Support custom functions in 'conditions'
- When matching edge, match 'any' src/tgt
- Support 'return'-statement in conditions? (just makes syntax nicer)
- RAMification / matching: add `match_subtypes` attribute to each RAMified class.
- Separate script for running LHS (+NAC) on any model, and visualizing the match.
- Syntax highlighting:
most students use:
- VS Code
- PyCharm
i use:
- Sublime Text
nobody uses:
- Eclipse

0
api/__init__.py Normal file
View file

View file

@ -53,7 +53,7 @@ class CDAPI:
return self.bottom.read_outgoing_elements(self.m, type_name)[0]
def is_direct_subtype(self, super_type_name: str, sub_type_name: str):
return sub_type_name in self.direct_sub_types[super_type]
return sub_type_name in self.direct_sub_types[super_type_name]
def is_direct_supertype(self, sub_type_name: str, super_type_name: str):
return super_type_name in self.direct_super_types[sub_type_name]
@ -83,3 +83,6 @@ class CDAPI:
result = self.find_attribute_type(supertype, attr_name)
if result != None:
return result
def get_type(self, type_name: str):
return next(k for k, v in self.type_model_names.items() if v == type_name)

View file

@ -6,8 +6,7 @@ from services.primitives.integer_type import Integer
from services.primitives.string_type import String
from services.primitives.actioncode_type import ActionCode
from uuid import UUID
from typing import Optional
from util.timer import Timer
from typing import Optional, Any
NEXT_ID = 0
@ -42,10 +41,10 @@ class ODAPI:
self.create_string_value = self.od.create_string_value
self.create_actioncode_value = self.od.create_actioncode_value
self.__recompute_mappings()
self.recompute_mappings()
# Called after every change - makes querying faster but modifying slower
def __recompute_mappings(self):
def recompute_mappings(self):
self.m_obj_to_name = build_name_mapping(self.state, self.m)
self.mm_obj_to_name = build_name_mapping(self.state, self.mm)
self.type_to_objs = { type_name : set() for type_name in self.bottom.read_keys(self.mm)}
@ -60,25 +59,33 @@ class ODAPI:
def get_value(self, obj: UUID):
return od.read_primitive_value(self.bottom, obj, self.mm)[0]
def get_target(self, link: UUID):
def get_target(self, link: UUID) -> UUID:
return self.bottom.read_edge_target(link)
def get_source(self, link: UUID):
def get_source(self, link: UUID) -> UUID:
return self.bottom.read_edge_source(link)
def get_slot(self, obj: UUID, attr_name: str):
def get_slot(self, obj: UUID, attr_name: str) -> UUID:
slot = self.od.get_slot(obj, attr_name)
if slot == None:
raise NoSuchSlotException(f"Object '{self.m_obj_to_name[obj]}' has no slot '{attr_name}'")
return slot
def get_slot_link(self, obj: UUID, attr_name: str):
def get_slot_link(self, obj: UUID, attr_name: str) -> UUID:
return self.od.get_slot_link(obj, attr_name)
# Parameter 'include_subtypes': whether to include subtypes of the given association
def get_outgoing(self, obj: UUID, assoc_name: str, include_subtypes=True):
def get_outgoing(self, obj: UUID, assoc_name: str, include_subtypes=True) -> list[UUID]:
outgoing = self.bottom.read_outgoing_edges(obj)
result = []
return self.filter_edges_by_type(outgoing, assoc_name, include_subtypes)
# Parameter 'include_subtypes': whether to include subtypes of the given association
def get_incoming(self, obj: UUID, assoc_name: str, include_subtypes=True):
incoming = self.bottom.read_incoming_edges(obj)
return self.filter_edges_by_type(incoming, assoc_name, include_subtypes)
def filter_edges_by_type(self, outgoing: list[UUID], assoc_name: str, include_subtypes=True) -> list[UUID]:
result: list[UUID] = []
for o in outgoing:
try:
type_of_outgoing_link = self.get_type_name(o)
@ -89,23 +96,8 @@ class ODAPI:
result.append(o)
return result
# Parameter 'include_subtypes': whether to include subtypes of the given association
def get_incoming(self, obj: UUID, assoc_name: str, include_subtypes=True):
incoming = self.bottom.read_incoming_edges(obj)
result = []
for i in incoming:
try:
type_of_incoming_link = self.get_type_name(i)
except:
continue # OK, not all edges are typed
if (include_subtypes and self.cdapi.is_subtype(super_type_name=assoc_name, sub_type_name=type_of_incoming_link)
or not include_subtypes and type_of_incoming_link == assoc_name):
result.append(i)
return result
# Returns list of tuples (name, obj)
def get_all_instances(self, type_name: str, include_subtypes=True):
def get_all_instances(self, type_name: str, include_subtypes=True) -> list[UUID]:
if include_subtypes:
all_types = self.cdapi.transitive_sub_types[type_name]
else:
@ -127,7 +119,7 @@ class ODAPI:
else:
raise Exception(f"Couldn't find name of {obj} - are you sure it exists in the (meta-)model?")
def get(self, name: str):
def get(self, name: str) -> UUID:
results = self.bottom.read_outgoing_elements(self.m, name)
if len(results) == 1:
return results[0]
@ -136,30 +128,32 @@ class ODAPI:
else:
raise Exception(f"No such element in model: '{name}'")
def get_type_name(self, obj: UUID):
def get_type_name(self, obj: UUID) -> str:
return self.get_name(self.get_type(obj))
def is_instance(self, obj: UUID, type_name: str, include_subtypes=True):
def is_instance(self, obj: UUID, type_name: str, include_subtypes=True) -> bool:
typ = self.cdapi.get_type(type_name)
types = set(typ) if not include_subtypes else self.cdapi.transitive_sub_types[type_name]
for type_of_obj in self.bottom.read_outgoing_elements(obj, "Morphism"):
if type_of_obj in types:
if self.get_name(type_of_obj) in types:
return True
return False
def delete(self, obj: UUID):
def delete(self, obj: UUID) -> None:
self.bottom.delete_element(obj)
self.__recompute_mappings()
self.recompute_mappings()
# Does the class of the object have the given attribute?
def has_slot(self, obj: UUID, attr_name: str):
# Does the the object have the given attribute?
def has_slot(self, obj: UUID, attr_name: str) -> bool:
class_name = self.get_name(self.get_type(obj))
return self.od.get_attr_link_name(class_name, attr_name) != None
if self.od.get_attr_link_name(class_name, attr_name) is None:
return False
return self.od.get_slot_link(obj, attr_name) is not None
def get_slots(self, obj: UUID) -> list[str]:
return [attr_name for attr_name, _ in self.od.get_slots(obj)]
def get_slot_value(self, obj: UUID, attr_name: str):
def get_slot_value(self, obj: UUID, attr_name: str) -> Any:
slot = self.get_slot(obj, attr_name)
return self.get_value(slot)
@ -172,14 +166,14 @@ class ODAPI:
# Returns the given default value if the slot does not exist on the object.
# The attribute must exist in the object's class, or an exception will be thrown.
# The slot may not exist however, if the attribute is defined as 'optional' in the class.
def get_slot_value_default(self, obj: UUID, attr_name: str, default: any):
def get_slot_value_default(self, obj: UUID, attr_name: str, default: any) -> any:
try:
return self.get_slot_value(obj, attr_name)
except NoSuchSlotException:
return default
# create or update slot value
def set_slot_value(self, obj: UUID, attr_name: str, new_value: any, is_code=False):
def set_slot_value(self, obj: UUID, attr_name: str, new_value: any, is_code=False) -> None:
obj_name = self.get_name(obj)
link_name = f"{obj_name}_{attr_name}"
@ -194,7 +188,7 @@ class ODAPI:
new_target = self.create_primitive_value(target_name, new_value, is_code)
slot_type = self.cdapi.find_attribute_type(self.get_type_name(obj), attr_name)
new_link = self.od._create_link(link_name, slot_type, obj, new_target)
self.__recompute_mappings()
self.recompute_mappings()
def create_primitive_value(self, name: str, value: any, is_code=False):
# watch out: in Python, 'bool' is subtype of 'int'
@ -210,7 +204,7 @@ class ODAPI:
tgt = self.create_string_value(name, value)
else:
raise Exception("Unimplemented type "+value)
self.__recompute_mappings()
self.recompute_mappings()
return tgt
def overwrite_primitive_value(self, name: str, value: any, is_code=False):
@ -229,7 +223,7 @@ class ODAPI:
else:
raise Exception("Unimplemented type "+value)
def create_link(self, link_name: Optional[str], assoc_name: str, src: UUID, tgt: UUID):
def create_link(self, link_name: Optional[str], assoc_name: str, src: UUID, tgt: UUID) -> UUID:
global NEXT_ID
types = self.bottom.read_outgoing_elements(self.mm, assoc_name)
if len(types) == 0:
@ -241,12 +235,12 @@ class ODAPI:
link_name = f"__{assoc_name}{NEXT_ID}"
NEXT_ID += 1
link_id = self.od._create_link(link_name, typ, src, tgt)
self.__recompute_mappings()
self.recompute_mappings()
return link_id
def create_object(self, object_name: Optional[str], class_name: str):
def create_object(self, object_name: Optional[str], class_name: str) -> UUID:
obj = self.od.create_object(object_name, class_name)
self.__recompute_mappings()
self.recompute_mappings()
return obj
# internal use
@ -262,6 +256,7 @@ def bind_api_readonly(odapi):
'get_target': odapi.get_target,
'get_source': odapi.get_source,
'get_slot': odapi.get_slot,
'get_slots': odapi.get_slots,
'get_slot_value': odapi.get_slot_value,
'get_slot_value_default': odapi.get_slot_value_default,
'get_all_instances': odapi.get_all_instances,
@ -270,6 +265,7 @@ def bind_api_readonly(odapi):
'get_outgoing': odapi.get_outgoing,
'get_incoming': odapi.get_incoming,
'has_slot': odapi.has_slot,
'is_instance': odapi.is_instance,
}
return funcs
@ -283,6 +279,6 @@ def bind_api(odapi):
'create_object': odapi.create_object,
'create_link': odapi.create_link,
'delete': odapi.delete,
'set_slot_value': odapi.set_slot_value,
'set_slot_value': odapi.set_slot_value
}
return funcs

9
api/od_stub.pyi Normal file
View file

@ -0,0 +1,9 @@
from typing import Optional
from uuid import UUID
from od_stub_readonly import *
def create_object(object_name: Optional[str], class_name: str) -> UUID: ...
def create_link(link_name: Optional[str], assoc_name: str, src: UUID, tgt: UUID) -> UUID: ...
def delete(obj: UUID) -> None: ...
def set_slot_value(obj: UUID, attr_name: str, new_value: any, is_code=False) -> None: ...

18
api/od_stub_readonly.pyi Normal file
View file

@ -0,0 +1,18 @@
from typing import Any
from uuid import UUID
def get(name: str) -> UUID: ...
def get_value(obj: UUID) -> Any: ...
def get_target(link: UUID) -> UUID: ...
def get_source(link: UUID) -> UUID: ...
def get_slot(obj: UUID, attr_name: str) -> UUID: ...
def get_slots(obj: UUID) -> list[str]: ...
def get_slot_value(obj: UUID, attr_name: str) -> Any: ...
def get_slot_value_default(obj: UUID, attr_name: str, default: any) -> Any: ...
def get_all_instances(type_name: str, include_subtypes=True) -> list[UUID]: ...
def get_name(obj: UUID) -> str: ...
def get_type_name(obj: UUID) -> str: ...
def get_outgoing(obj: UUID, assoc_name: str, include_subtypes=True) -> list[UUID]: ...
def get_incoming(obj: UUID, assoc_name: str, include_subtypes: object = True) -> list[UUID]: ...
def has_slot(obj: UUID, attr_name: str) -> bool: ...
def is_instance(obj: UUID, type_name: str, include_subtypes=True) -> bool: ...

View file

@ -47,7 +47,7 @@ def bootstrap_constraint(class_node, type_name: str, python_type: str, scd_root:
bottom.create_edge(constraint_node, scd_node, "Morphism")
bottom.create_edge(constraint_link, scd_link, "Morphism")
def bootstrap_primitive_types(scd_root, state, integer_type, boolean_type, float_type, string_type, type_type, actioncode_type):
def bootstrap_primitive_types(scd_root, state, integer_type, boolean_type, float_type, string_type, type_type, actioncode_type, bytes_type):
# Order is important: Integer must come first
class_integer = bootstrap_type("Integer", scd_root, integer_type, state)
class_type = bootstrap_type("Type", scd_root, type_type, state)
@ -55,6 +55,7 @@ def bootstrap_primitive_types(scd_root, state, integer_type, boolean_type, float
class_float = bootstrap_type("Float", scd_root, float_type, state)
class_string = bootstrap_type("String", scd_root, string_type, state)
class_actioncode = bootstrap_type("ActionCode", scd_root, actioncode_type, state)
class_bytes = bootstrap_type("Bytes", scd_root, bytes_type, state)
# Can only create constraints after ActionCode type has been created:
bootstrap_constraint(class_integer, "Integer", "int", scd_root, integer_type, actioncode_type, state)
@ -63,3 +64,4 @@ def bootstrap_primitive_types(scd_root, state, integer_type, boolean_type, float
bootstrap_constraint(class_float, "Float", "float", scd_root, float_type, actioncode_type, state)
bootstrap_constraint(class_string, "String", "str", scd_root, string_type, actioncode_type, state)
bootstrap_constraint(class_actioncode, "ActionCode", "str", scd_root, actioncode_type, actioncode_type, state)
bootstrap_constraint(class_bytes, "Bytes", "bytes", scd_root, bytes_type, actioncode_type, state)

View file

@ -2,15 +2,7 @@ from state.base import State, UUID
from services.bottom.V0 import Bottom
from services.primitives.boolean_type import Boolean
from services.primitives.string_type import String
from bootstrap.primitive import (
bootstrap_primitive_types
# bootstrap_boolean_type,
# bootstrap_float_type,
# bootstrap_integer_type,
# bootstrap_string_type,
# bootstrap_type_type,
# bootstrap_actioncode_type
)
from bootstrap.primitive import bootstrap_primitive_types
def create_model_root(bottom: Bottom, model_name: str) -> UUID:
@ -32,6 +24,7 @@ def bootstrap_scd(state: State) -> UUID:
float_type_root = create_model_root(bottom, "Float")
type_type_root = create_model_root(bottom, "Type")
actioncode_type_root = create_model_root(bottom, "ActionCode")
bytes_type_root = create_model_root(bottom, "Bytes")
# create MCL, without morphism links
@ -85,8 +78,7 @@ def bootstrap_scd(state: State) -> UUID:
add_edge_element("gc_inh_element", glob_constr_node, element_node)
# # Attribute inherits from Element
add_edge_element("attr_inh_element", attr_node, element_node)
# # Association inherits from Element
# add_edge_element("assoc_inh_element", assoc_edge, element_node)
# # Association inherits from Class
add_edge_element("assoc_inh_element", assoc_edge, class_node)
# # AttributeLink inherits from Element
add_edge_element("attr_link_inh_element", attr_link_edge, element_node)
@ -132,7 +124,8 @@ def bootstrap_scd(state: State) -> UUID:
float_type_root,
string_type_root,
type_type_root,
actioncode_type_root)
actioncode_type_root,
bytes_type_root)
# bootstrap_integer_type(mcl_root, integer_type_root, integer_type_root, actioncode_type_root, state)
# bootstrap_boolean_type(mcl_root, boolean_type_root, integer_type_root, actioncode_type_root, state)
# bootstrap_float_type(mcl_root, float_type_root, integer_type_root, actioncode_type_root, state)

View file

@ -16,6 +16,8 @@ def display_value(val: any, type_name: str, indentation=0, newline_character='\n
return '"'+val+'"'.replace('\n', newline_character)
elif type_name == "Integer" or type_name == "Boolean":
return str(val)
elif type_name == "Bytes":
return val
else:
raise Exception("don't know how to display value" + type_name)
@ -48,6 +50,9 @@ class TBase(Transformer):
def CODE(self, token):
return _Code(str(token[1:-1])) # strip the ``
def BYTES(self, token):
return (bytes(token[2:-1], "utf-8"), token.line) # Strip b"" or b''
def INDENTED_CODE(self, token):
skip = 4 # strip the ``` and the following newline character
space_count = 0

View file

@ -40,7 +40,7 @@ attrs: attr*
constraint: CODE | INDENTED_CODE
class_: [ABSTRACT] "class" IDENTIFIER [multiplicity] ["(" superclasses ")"] ["{" attrs [constraint] "}"]
class_: [ABSTRACT] "class" IDENTIFIER [multiplicity] ["(" superclasses ")"] ["{" attrs [constraint ";"] "}"]
association: "association" IDENTIFIER [multiplicity] IDENTIFIER "->" IDENTIFIER [multiplicity] ["{" attrs [constraint] "}"]
@ -75,7 +75,7 @@ def parse_cd(state, m_text):
primitive_types = {
type_name : UUID(state.read_value(state.read_dict(state.read_root(), type_name)))
for type_name in ["Integer", "String", "Boolean"]
for type_name in ["Integer", "String", "Boolean", "ActionCode"]
}
class T(TBase):

View file

@ -1,18 +1,23 @@
{% macro render_name(name) %}{{ name if not hide_names or name.startswith("__") else "" }}{% endmacro %}
{% macro render_attributes(obj) %} {
{% macro render_attributes(obj) %}
{% if len(odapi.get_slots(obj)) > 0 %} {
{% for attr_name in odapi.get_slots(obj) %}
{{ attr_name}} = {{ display_value(
val=odapi.get_slot_value(obj, attr_name),
type_name=odapi.get_type_name(odapi.get_slot(obj, attr_name)),
indentation=4) }};
{% endfor %}
}{% endmacro %}
{% endfor -%}
}
{% endif -%}
{%- endmacro %}
{% for obj_name, obj in objects %}
{{ render_name(obj_name) }}:{{ odapi.get_type_name(obj) }}{{ render_attributes(obj) }}
{% endfor %}
{%- for obj_name, obj in objects %}
{{ render_name(obj_name) }}:{{ odapi.get_type_name(obj) }}
{{- render_attributes(obj) }}
{% endfor -%}
{% for lnk_name, lnk in links %}
{{ render_name(obj_name) }}:{{ odapi.get_type_name(lnk) }} ({{odapi.get_name(odapi.get_source(lnk))}} -> {{odapi.get_name(odapi.get_target(lnk))}}){{ render_attributes(lnk) }}
{% endfor %}
{%- for lnk_name, lnk in links %}
{{ render_name(obj_name) }}:{{ odapi.get_type_name(lnk) }} ({{odapi.get_name(odapi.get_source(lnk))}} -> {{odapi.get_name(odapi.get_target(lnk))}})
{{- render_attributes(lnk) }}
{% endfor -%}

View file

@ -21,6 +21,7 @@ literal: INT
| STR
| BOOL
| CODE
| BYTES
| INDENTED_CODE
INT: /[0-9]+/
@ -28,6 +29,8 @@ STR: /"[^"]*"/
| /'[^']*'/
BOOL: "True" | "False"
CODE: /`[^`]*`/
BYTES: /b"[^"]*"/
| /b'[^']*'/
INDENTED_CODE: /```[^`]*```/
type_name: IDENTIFIER
@ -67,7 +70,7 @@ def parse_od(state,
primitive_types = {
type_name : UUID(state.read_value(state.read_dict(state.read_root(), type_name)))
for type_name in ["Integer", "String", "Boolean", "ActionCode"]
for type_name in ["Integer", "String", "Boolean", "ActionCode", "Bytes"]
}
class T(Transformer):
@ -89,6 +92,10 @@ def parse_od(state,
def CODE(self, token):
return (_Code(str(token[1:-1])), token.line) # strip the ``
def BYTES(self, token):
# Strip b"" or b'', and make \\ back to \ (happens when reading the file as a string)
return (token[2:-1].encode().decode('unicode_escape').encode('raw_unicode_escape'), token.line) # Strip b"" or b''
def INDENTED_CODE(self, token):
skip = 4 # strip the ``` and the following newline character
space_count = 0

View file

@ -9,7 +9,7 @@ def render_od(state, m_id, mm_id, hide_names=True):
m_od = od.OD(mm_id, m_id, state)
serialized = set(["Integer", "String", "Boolean", "ActionCode"]) # assume these types always already exist
serialized = set(["Integer", "String", "Boolean", "ActionCode", "Bytes"]) # assume these types always already exist
def display_name(name: str):
# object names that start with "__" are hidden

3
doc/odapi/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*.aux
*.log
*.out

BIN
doc/odapi/api_table.pdf Normal file

Binary file not shown.

121
doc/odapi/api_table.tex Normal file
View file

@ -0,0 +1,121 @@
\documentclass{article}
\usepackage[left=1cm, right=1cm]{geometry} % reduce page margins
\usepackage{amssymb}
\usepackage{booktabs}
\usepackage[normalem]{ulem}
\usepackage[utf8]{inputenc}
\usepackage{hyperref}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{color,listings}
\usepackage{awesomebox}
\newcommand{\specialcell}[2][c]{%
\begin{tabular}[#1]{@{}l@{}}#2\end{tabular}}
\def\ck{\checkmark}
\begin{document}
\centering
\begin{scriptsize}
\begin{tabular}{|l|c|c|c|c|c|l|}
\hline
& \multicolumn{5}{c|}{Availability in Context} & \\
\hline
& \multicolumn{2}{c|}{ \specialcell{Meta-Model \\ Constraint}} & \multicolumn{2}{c|}{ \specialcell{Model Trans- \\ formation Rule} } & & \\
\hline
& \specialcell{ \textbf{Local} }
& \specialcell{ \textbf{Global} }
& \specialcell{ \textbf{NAC} \\ \textbf{LHS} }
& \textbf{RHS}
& \specialcell{ \textbf{OD-} \\ \textbf{API} }
& \textbf{Meaning} \\
\hline
\hline
\multicolumn{7}{|l|}{\textit{Querying}} \\
\hline
\texttt{this :obj} & \ck & & \ck & \ck & & Current object or link \\
\hline
\texttt{get\_name(:obj) :str} & \ck & \ck & \ck & \ck & \ck & Get name of object or link \\
\hline
\texttt{get(name:str) :obj} & \ck & \ck & \ck & \ck & \ck & Get object or link by name (inverse of \texttt{get\_name}) \\
\hline
\texttt{get\_type(:obj) :obj} & \ck & \ck & \ck & \ck & \ck & {Get type of object or link} \\
\hline
\texttt{get\_type\_name(:obj) :str} & \ck & \ck & \ck & \ck & \ck & {Same as \texttt{get\_name(get\_type(...))}} \\
\hline
\specialcell{
\texttt{is\_instance(:obj, type\_name:str}
\\ \texttt{ [,include\_subtypes:bool=True]) :bool}
} & \ck & \ck & \ck & \ck & \ck & \specialcell{Is object instance of given type\\(or subtype thereof)?} \\
\hline
\texttt{get\_value(:obj) :int|str|bool} & \ck & \ck & \ck & \ck & \ck & \specialcell{Get value (only works on Integer,\\String, Boolean objects)} \\
\hline
\texttt{get\_target(:link) :obj} & \ck & \ck & \ck & \ck & \ck & {Get target of link} \\
\hline
\texttt{get\_source(:link) :obj} & \ck & \ck & \ck & \ck & \ck & {Get source of link} \\
\hline
\texttt{get\_slot(:obj, attr\_name:str) :link} & \ck & \ck & \ck & \ck & \ck & {Get slot-link (link connecting object to a value)} \\
\hline
\specialcell{
\texttt{get\_slot\_value(:obj,}
\\ \texttt{attr\_name:str) :int|str|bool}
} & \ck & \ck & \ck & \ck & \ck & {Same as \texttt{get\_value(get\_slot(...))})} \\
\hline
\specialcell{
\texttt{get\_all\_instances(type\_name:str}
\\ \texttt{ [,include\_subtypes:bool=True]}
\\ \texttt{) :list<(str, obj)>}
} & \ck & \ck & \ck & \ck & \ck & \specialcell{Get list of tuples (name, object) \\ of given type (and its subtypes).} \\
\hline
\specialcell{
\texttt{get\_outgoing(:obj,}
\\ \texttt{ assoc\_name:str) :list<link>}
} & \ck & \ck & \ck & \ck & \ck & {Get outgoing links of given type} \\
\hline
\specialcell{
\texttt{get\_incoming(:obj,}
\\ \texttt{ assoc\_name:str) :list<link>}
} & \ck & \ck & \ck & \ck & \ck & {Get incoming links of given type} \\
\hline
\texttt{has\_slot(:obj, attr\_name:str) :bool} & \ck & \ck & \ck & \ck & \ck & {Does object have given slot?} \\
\hline
\texttt{matched(label:str) :obj} & & & \ck & \ck & & \specialcell{Get matched object by its label \\ (the name of the object in the pattern)} \\
\hline
\hline
\multicolumn{7}{|l|}{\textit{Modifying}} \\
\hline
\texttt{delete(:obj)} & & & & \ck & \ck & {Delete object or link} \\
\hline
\specialcell{
\texttt{set\_slot\_value(:obj, attr\_name:str,}
\\ \texttt{ val:int|str|bool)}
} & & & & \ck & \ck & \specialcell{Set value of slot.
\\ Creates slot if it doesn't exist yet.} \\
\hline
\specialcell{
\texttt{create\_link(link\_name:str|None,} \\
\texttt{ assoc\_name:str, src:obj, tgt:obj) :link}
} & & & & \ck & \ck & \specialcell{Create link (typed by given association). \\
If \texttt{link\_name} is None, name is auto-generated.} \\
\hline
\specialcell{
\texttt{create\_object(object\_name:str|None,} \\
\texttt{ class\_name:str) :obj}
} & & & & \ck & \ck & \specialcell{Create object (typed by given class). \\
If \texttt{object\_name} is None, name is auto-generated.} \\
\hline
% \texttt{print(*args)} & \multicolumn{2}{c|}{Python's print function (useful for debugging)} & no, use the real print() \\
\end{tabular}
\end{scriptsize}
\end{document}

View file

@ -1,75 +0,0 @@
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from framework.conformance import Conformance, render_conformance_check_result
from concrete_syntax.textual_od import parser, renderer
from concrete_syntax.common import indent
from concrete_syntax.plantuml import renderer as plantuml
from util.prompt import yes_no, pause
state = DevState()
scd_mmm = bootstrap_scd(state)
mm_cs = """
BaseA:Class {
abstract = True;
}
BaseB:Class {
abstract = True;
}
baseAssoc:Association (BaseA -> BaseB) {
abstract = True;
target_lower_cardinality = 1;
target_upper_cardinality = 2; # A has 1..2 B
}
A:Class
B:Class
assoc:Association (A -> B) {
# we can further restrict cardinality from baseAssoc:
target_upper_cardinality = 1;
# relaxing cardinalities or constraints can be done (meaning: it will still be a valid meta-model), but will have no effect: for any instance of a type, the constraints defined on the type and its supertypes will be checked.
}
:Inheritance (A -> BaseA)
:Inheritance (B -> BaseB)
:Inheritance (assoc -> baseAssoc)
"""
print()
print("Parsing meta-model...")
mm = parser.parse_od(
state,
m_text=mm_cs, # the string of text to parse
mm=scd_mmm, # the meta-model of class diagrams (= our meta-meta-model)
)
print("OK")
print("Is our meta-model a valid class diagram?")
conf = Conformance(state, mm, scd_mmm)
print(render_conformance_check_result(conf.check_nominal()))
m_cs = """
a0:A
b0:B
b1:B
# error: assoc (A -> B) must have tgt card 0..1 (and we have 2 instead)
:assoc (a0 -> b0)
:assoc (a0 -> b1)
# error: baseAssoc (A -> B) must have tgt card 1..2 (and we have 0 instead)
a1:A
"""
print()
print("Parsing model...")
m = parser.parse_od(
state,
m_text=m_cs,
mm=mm, # this time, the meta-model is the previous model we parsed
)
print("OK")
print("Is our model a valid woods-diagram?")
conf = Conformance(state, m, mm)
print(render_conformance_check_result(conf.check_nominal()))

View file

@ -1,27 +0,0 @@
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from services.scd import SCD
from concrete_syntax.plantuml import renderer as plantuml
def main():
state = DevState()
root = state.read_root() # id: 0
scd_mm_id = bootstrap_scd(state)
uml = ""
# Render SCD Meta-Model as Object Diagram
uml += plantuml.render_package("Object Diagram", plantuml.render_object_diagram(state, scd_mm_id, scd_mm_id, prefix_ids="od_"))
# Render SCD Meta-Model as Class Diagram
uml += plantuml.render_package("Class Diagram", plantuml.render_class_diagram(state, scd_mm_id, prefix_ids="cd_"))
# Render conformance
uml += plantuml.render_trace_conformance(state, scd_mm_id, scd_mm_id, prefix_inst_ids="od_", prefix_type_ids="cd_")
print(uml)
if __name__ == "__main__":
main()

View file

@ -1,202 +0,0 @@
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from framework.conformance import Conformance, render_conformance_check_result
from concrete_syntax.textual_od import parser, renderer
from concrete_syntax.common import indent
from concrete_syntax.plantuml import renderer as plantuml
from util.prompt import yes_no, pause
state = DevState()
print("Loading meta-meta-model...")
scd_mmm = bootstrap_scd(state)
print("OK")
print("Is our meta-meta-model a valid class diagram?")
conf = Conformance(state, scd_mmm, scd_mmm)
print(render_conformance_check_result(conf.check_nominal()))
# If you are curious, you can serialize the meta-meta-model:
# print("--------------")
# print(indent(
# renderer.render_od(state,
# m_id=scd_mmm,
# mm_id=scd_mmm),
# 4))
# print("--------------")
# Change this:
woods_mm_cs = """
Animal:Class {
# The class Animal is an abstract class:
abstract = True;
}
# A class without attributes
# The `abstract` attribute shown above is optional (default: False)
Bear:Class
# Inheritance between two Classes is expressed as follows:
:Inheritance (Bear -> Animal) # meaning: Bear is an Animal
Man:Class {
# We can define lower and upper cardinalities on Classes
# (if unspecified, the lower-card is 0, and upper-card is infinity)
lower_cardinality = 1; # there must be at least one Man in every model
upper_cardinality = 2; # there must be at most two Men in every model
constraint = ```
# Python code
# the last statement must be a boolean expression
# When conformance checking, this code will be run for every Man-object.
# The variable 'this' refers to the current Man-object.
# Every man weighs at least '20'
# (the attribute 'weight' is added further down)
get_value(get_slot(this, "weight")) > 20
```;
}
# Note that we can only declare the inheritance link after having declared both Man and Animal: We can only refer to earlier objects
:Inheritance (Man -> Animal) # Man is also an Animal
# BTW, we could also give the Inheritance-link a name, for instance:
# man_is_animal:Inheritance (Man -> Animal)
#
# Likewise, Classes, Associations, ... can also be nameless, for instance:
# :Class { ... }
# :Association (Man -> Man) { ... }
# However, we typically want to give names to classes and associations, because we want to refer to them later.
# We now add an attribute to 'Man'
# Attributes are not that different from Associations: both are represented by links
Man_weight:AttributeLink (Man -> Integer) {
name = "weight"; # mandatory!
optional = False; # <- meaning: every Man *must* have a weight
# We can also define constraints on attributes
constraint = ```
# Python code
# Here, 'this' refers to the LINK that connects a Man-object to an Integer
tgt = get_target(this) # <- we get the target of the LINK (an Integer-object)
weight = get_value(tgt) # <- get the Integer-value (e.g., 80)
weight > 20
```;
}
# Create an Association from Man to Animal
afraidOf:Association (Man -> Animal) {
# An association has the following (optional) attributes:
# - source_lower_cardinality (default: 0)
# - source_upper_cardinality (default: infinity)
# - target_lower_cardinality (default: 0)
# - target_upper_cardinality (default: infinity)
# Every Man is afraid of at least one Animal:
target_lower_cardinality = 1;
# No more than 6 Men are afraid of the same Animal:
source_upper_cardinality = 6;
}
# Create a GlobalConstraint
total_weight_small_enough:GlobalConstraint {
# Note: for GlobalConstraints, there is no 'this'-variable
constraint = ```
# Python code
# compute sum of all weights
total_weight = 0
for man_name, man_id in get_all_instances("Man"):
total_weight += get_value(get_slot(man_id, "weight"))
# as usual, the last statement is a boolean expression that we think should be satisfied
total_weight < 85
```;
}
"""
print()
print("Parsing 'woods' meta-model...")
woods_mm = parser.parse_od(
state,
m_text=woods_mm_cs, # the string of text to parse
mm=scd_mmm, # the meta-model of class diagrams (= our meta-meta-model)
)
print("OK")
# As a double-check, you can serialize the parsed model:
# print("--------------")
# print(indent(
# renderer.render_od(state,
# m_id=woods_mm,
# mm_id=scd_mmm),
# 4))
# print("--------------")
print("Is our 'woods' meta-model a valid class diagram?")
conf = Conformance(state, woods_mm, scd_mmm)
print(render_conformance_check_result(conf.check_nominal()))
# Change this:
woods_m_cs = """
george:Man {
weight = 15;
}
billy:Man {
weight = 100;
}
bear1:Bear
bear2:Bear
:afraidOf (george -> bear1)
:afraidOf (george -> bear2)
"""
print()
print("Parsing 'woods' model...")
woods_m = parser.parse_od(
state,
m_text=woods_m_cs,
mm=woods_mm, # this time, the meta-model is the previous model we parsed
)
print("OK")
# As a double-check, you can serialize the parsed model:
# print("--------------")
# print(indent(
# renderer.render_od(state,
# m_id=woods_m,
# mm_id=woods_mm),
# 4))
# print("--------------")
print("Is our model a valid woods-diagram?")
conf = Conformance(state, woods_m, woods_mm)
print(render_conformance_check_result(conf.check_nominal()))
print()
print("==================================")
if yes_no("Print PlantUML?"):
print_mm = yes_no(" ▸ Print meta-model?")
print_m = yes_no(" ▸ Print model?")
print_conf = print_mm and print_m and yes_no(" ▸ Print conformance links?")
uml = ""
if print_mm:
uml += plantuml.render_package("Meta-model", plantuml.render_class_diagram(state, woods_mm))
if print_m:
uml += plantuml.render_package("Model", plantuml.render_object_diagram(state, woods_m, woods_mm))
if print_conf:
uml += plantuml.render_trace_conformance(state, woods_m, woods_mm)
print("==================================")
print(uml)
print("==================================")
print("Go to either:")
print(" ▸ https://www.plantuml.com/plantuml/uml")
print(" ▸ https://mstro.duckdns.org/plantuml/uml")
print("and paste the above string.")

View file

@ -1,133 +0,0 @@
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from framework.conformance import Conformance, render_conformance_check_result
from concrete_syntax.textual_cd import parser as parser_cd
from concrete_syntax.textual_od import parser as parser_od
from concrete_syntax.textual_od import renderer as renderer_od
from concrete_syntax.common import indent
from concrete_syntax.plantuml import renderer as plantuml
from util.prompt import yes_no, pause
state = DevState()
print("Loading meta-meta-model...")
scd_mmm = bootstrap_scd(state)
print("OK")
print("Is our meta-meta-model a valid class diagram?")
conf = Conformance(state, scd_mmm, scd_mmm)
print(render_conformance_check_result(conf.check_nominal()))
# If you are curious, you can serialize the meta-meta-model:
# print("--------------")
# print(indent(
# renderer.render_od(state,
# m_id=scd_mmm,
# mm_id=scd_mmm),
# 4))
# print("--------------")
# Change this:
woods_mm_cs = """
abstract class Animal
class Bear (Animal) # Bear inherits Animal
class Man [1..2] (Animal) {
Integer weight `get_value(get_target(this)) > 20`; # <- constraint in context of attribute-link
`get_value(get_slot(this, "weight")) > 20` # <- constraint in context of Man-object
}
association afraidOf [0..6] Man -> Animal [1..2]
global total_weight_small_enough ```
total_weight = 0
for man_name, man_id in get_all_instances("Man"):
total_weight += get_value(get_slot(man_id, "weight"))
total_weight < 85
```
"""
print()
print("Parsing 'woods' meta-model...")
woods_mm = parser_cd.parse_cd(
state,
m_text=woods_mm_cs, # the string of text to parse
)
print("OK")
# We can serialize the class diagram to our object diagram syntax
# (because the class diagram IS also an object diagram):
print("--------------")
print(indent(
renderer_od.render_od(state,
m_id=woods_mm,
mm_id=scd_mmm),
4))
print("--------------")
print("Is our 'woods' meta-model a valid class diagram?")
conf = Conformance(state, woods_mm, scd_mmm)
print(render_conformance_check_result(conf.check_nominal()))
# Change this:
woods_m_cs = """
george:Man {
weight = 15;
}
billy:Man {
weight = 100;
}
bear1:Bear
bear2:Bear
:afraidOf (george -> bear1)
:afraidOf (george -> bear2)
"""
print()
print("Parsing 'woods' model...")
woods_m = parser_od.parse_od(
state,
m_text=woods_m_cs,
mm=woods_mm, # this time, the meta-model is the previous model we parsed
)
print("OK")
# As a double-check, you can serialize the parsed model:
# print("--------------")
# print(indent(
# renderer.render_od(state,
# m_id=woods_m,
# mm_id=woods_mm),
# 4))
# print("--------------")
print("Is our model a valid woods-diagram?")
conf = Conformance(state, woods_m, woods_mm)
print(render_conformance_check_result(conf.check_nominal()))
print()
print("==================================")
if yes_no("Print PlantUML?"):
print_mm = yes_no(" ▸ Print meta-model?")
print_m = yes_no(" ▸ Print model?")
print_conf = print_mm and print_m and yes_no(" ▸ Print conformance links?")
uml = ""
if print_mm:
uml += plantuml.render_package("Meta-model", plantuml.render_class_diagram(state, woods_mm))
if print_m:
uml += plantuml.render_package("Model", plantuml.render_object_diagram(state, woods_m, woods_mm))
if print_conf:
uml += plantuml.render_trace_conformance(state, woods_m, woods_mm)
print("==================================")
print(uml)
print("==================================")
print("Go to either:")
print(" ▸ https://www.plantuml.com/plantuml/uml")
print(" ▸ https://mstro.duckdns.org/plantuml/uml")
print("and paste the above string.")

View file

@ -0,0 +1,47 @@
import os
# Todo: remove src.backend.muMLE from the imports
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from concrete_syntax.textual_od.parser import parse_od
from api.od import ODAPI
from concrete_syntax.textual_od.renderer import render_od as od_renderer
from concrete_syntax.plantuml import make_url as plant_url, renderer as plant_renderer
from concrete_syntax.graphviz import make_url as graphviz_url, renderer as graphviz_renderer
class FtgPmPt:
def __init__(self, name: str):
self.state = DevState()
self.scd_mmm = bootstrap_scd(self.state)
self.meta_model = self.load_metamodel()
self.model = None
self.odapi = None
self.name = name
@staticmethod
def read_file(file_name):
with open(os.path.join(os.path.dirname(__file__), file_name)) as file:
return file.read()
def load_metamodel(self):
mm_cs = self.read_file("pm/metamodels/mm_design.od")
mm_rt_cs = mm_cs + self.read_file("pm/metamodels/mm_runtime.od")
mm_total = mm_rt_cs + self.read_file("pt/metamodels/mm_design.od")
return parse_od(self.state, m_text=mm_total, mm=self.scd_mmm)
def load_model(self, m_text: str | None = None):
m_text = "" if not m_text else m_text
self.model = parse_od(self.state, m_text=m_text, mm=self.meta_model)
self.odapi = ODAPI(self.state, self.model, self.meta_model)
def render_od(self):
return od_renderer(self.state, self.model, self.meta_model, hide_names=False)
def render_plantuml_object_diagram(self):
print(plant_url.make_url(plant_renderer.render_package(
self.name, plant_renderer.render_object_diagram(self.state, self.model, self.meta_model)))
)
def render_graphviz_object_diagram(self):
print(graphviz_url.make_url(graphviz_renderer.render_object_diagram(self.state, self.model, self.meta_model)))

View file

@ -0,0 +1,68 @@
import copy
import pickle
from api.od import ODAPI
from examples.ftg_pm_pt.helpers.composite_activity import execute_composite_workflow
def serialize(obj):
return pickle.dumps(obj)
def deserialize(obj):
return pickle.loads(obj)
def create_activity_links(od: ODAPI, activity, prev_element, ctrl_port, end_trace=None,
relation_type="pt_IsFollowedBy"):
od.create_link(None, "pt_RelatesTo", activity, ctrl_port)
od.create_link(None, relation_type, prev_element, activity)
if end_trace:
od.create_link(None, "pt_IsFollowedBy", activity, end_trace)
def extract_input_data(od: ODAPI, activity):
input_data = {}
for has_data_in in od.get_outgoing(activity, "pm_HasDataIn"):
data_port = od.get_target(has_data_in)
artefact_state = od.get_source(od.get_incoming(od.get_source(od.get_incoming(data_port, "pm_DataFlowOut")[0]), "pm_Of")[0])
input_data[od.get_name(data_port)] = deserialize(od.get_slot_value(artefact_state, "data"))
return input_data
def execute_activity(od: ODAPI, globs, activity, input_data):
inp = copy.deepcopy(input_data) # Necessary, otherwise the function changes the values inside the dictionary -> need the original values for process trace
func = globs[od.get_slot_value(activity, "func")]
return func(inp) if func.__code__.co_argcount > 0 else func()
def handle_artefact(od: ODAPI, activity, artefact_type, relation_type, data_port=None, data=None,
direction="DataFlowIn"):
artefact = od.create_object(None, "pt_Artefact")
if 'pt_Consumes' == relation_type:
od.create_link(None, relation_type, artefact, activity)
else:
od.create_link(None, relation_type, activity, artefact)
if data_port:
flow_direction = od.get_incoming if relation_type == 'pt_Consumes' else od.get_outgoing
ass_side = od.get_source if relation_type == 'pt_Consumes' else od.get_target
pm_artefact = ass_side(flow_direction(data_port, f"pm_{direction}")[0])
prev_artefact = find_previous_artefact(od, od.get_incoming(pm_artefact, "pt_BelongsTo"))
if prev_artefact:
od.create_link(None, "pt_PrevVersion", artefact, prev_artefact)
od.create_link(None, "pt_BelongsTo", artefact, pm_artefact)
if data is not None:
artefact_state = od.get_source(od.get_incoming(pm_artefact, "pm_Of")[0])
od.set_slot_value(artefact_state, "data", serialize(data))
od.set_slot_value(artefact, "data", serialize(data))
def find_previous_artefact(od: ODAPI, linked_artefacts):
return next((od.get_source(link) for link in linked_artefacts if
not od.get_incoming(od.get_source(link), "pt_PrevVersion")), None)
def update_control_states(od: ODAPI, activity, ctrl_out):
for has_ctrl_in in od.get_outgoing(activity, "pm_HasCtrlIn"):
od.set_slot_value(od.get_source(od.get_incoming(od.get_target(has_ctrl_in), "pm_Of")[0]), "active", False)
od.set_slot_value(od.get_source(od.get_incoming(ctrl_out, "pm_Of")[0]), "active", True)

View file

@ -0,0 +1,272 @@
from uuid import UUID
from api.od import ODAPI
from examples.ftg_pm_pt.ftg_pm_pt import FtgPmPt
from examples.ftg_pm_pt.runner import FtgPmPtRunner
def find_previous_artefact(od: ODAPI, linked_artefacts):
return next((od.get_source(link) for link in linked_artefacts if
not od.get_incoming(od.get_source(link), "pt_PrevVersion")), None)
def create_activity_links(od: ODAPI, activity, prev_element, ctrl_port, end_trace=None,
relation_type="pt_IsFollowedBy"):
od.create_link(None, "pt_RelatesTo", activity, ctrl_port)
od.create_link(None, relation_type, prev_element, activity)
if end_trace:
od.create_link(None, "pt_IsFollowedBy", activity, end_trace)
def get_workflow_path(od: ODAPI, activity: UUID):
return od.get_slot_value(activity, "subworkflow_path")
def get_workflow(workflow_path: str):
with open(workflow_path, "r") as f:
return f.read()
############################
def get_runtime_state(od: ODAPI, design_obj: UUID):
states = od.get_incoming(design_obj, "pm_Of")
if len(states) == 0:
print(f"Design object '{od.get_name(design_obj)}' has no runtime state.")
return None
return od.get_source(states[0])
def get_source_incoming(od: ODAPI, obj: UUID, link_name: str):
links = od.get_incoming(obj, link_name)
if len(links) == 0:
print(f"Object '{od.get_name(obj)} has no incoming links of type '{link_name}'.")
return None
return od.get_source(links[0])
def get_target_outgoing(od: ODAPI, obj: UUID, link_name: str):
links = od.get_outgoing(obj, link_name)
if len(links) == 0:
print(f"Object '{od.get_name(obj)} has no outgoing links of type '{link_name}'.")
return None
return od.get_target(links[0])
def set_control_port_value(od: ODAPI, port: UUID, value: bool):
state = get_runtime_state(od, port)
od.set_slot_value(state, "active", value)
def set_artefact_data(od: ODAPI, artefact: UUID, value: bytes):
state = artefact
# Only the proces model of the artefact contains a runtime state
if od.get_type_name(state) == "pm_Artefact":
state = get_runtime_state(od, artefact)
od.set_slot_value(state, "data", value)
def get_artefact_data(od: ODAPI, artefact):
state = artefact
# Only the proces model of the artefact contains a runtime state
if od.get_type_name(state) == "pm_Artefact":
state = get_runtime_state(od, artefact)
return od.get_slot_value(state, "data")
############################
def set_workflow_control_source(workflow_model: FtgPmPt, ctrl_port_name: str, composite_linkage: dict):
od = workflow_model.odapi
source_port_name = composite_linkage[ctrl_port_name]
source_port = od.get(source_port_name)
set_control_port_value(od, source_port, True)
def set_workflow_artefacts(act_od: ODAPI, activity: UUID, workflow_model: FtgPmPt, composite_linkage: dict):
for data_port in [act_od.get_target(data_in) for data_in in act_od.get_outgoing(activity, "pm_HasDataIn")]:
# Get the data source port of the inner workflow
data_port_name = act_od.get_name(data_port)
source_port_name = composite_linkage[data_port_name]
source_port = workflow_model.odapi.get(source_port_name)
# Get the artefact that is linked to the data port of the activity
act_artefact = get_source_incoming(act_od, data_port, "pm_DataFlowOut")
# Get the data of the artefact
artefact_data = get_artefact_data(act_od, act_artefact)
# Get the artefact that is linked to the data port of the inner workflow
workflow_artefact = get_target_outgoing(workflow_model.odapi, source_port, "pm_DataFlowIn")
set_artefact_data(workflow_model.odapi, workflow_artefact, artefact_data)
def get_activity_port_from_inner_port(composite_linkage: dict, port_name: str):
for act_port_name, work_port_name in composite_linkage.items():
if work_port_name == port_name:
return act_port_name
def execute_composite_workflow(od: ODAPI, activity: UUID, ctrl_port: UUID, composite_linkage: dict,
packages: dict | None, matched=None):
activity_name = od.get_slot_value(activity, "name")
# First get the path of the object diagram file that contains the inner workflow of the activity
workflow_path = get_workflow_path(od, activity)
# Read the object diagram file
workflow = get_workflow(workflow_path)
# Create an FtgPmPt object
workflow_model = FtgPmPt(activity_name)
# Load the workflow to the object
workflow_model.load_model(workflow)
# Set the correct control source port of the workflow to active
set_workflow_control_source(workflow_model, od.get_name(ctrl_port), composite_linkage[activity_name])
# If a data port is linked, set the data of the artefact
set_workflow_artefacts(od, activity, workflow_model, composite_linkage[activity_name])
# Create an FtgPmPtRunner object with the FtgPmPt object
workflow_runner = FtgPmPtRunner(workflow_model)
# Set the packages if present
workflow_runner.set_packages(packages, is_path=False)
# Run the FtgPmPtRunner (is a subprocess necessary? This makes it more complicated because now we have direct access to the object)
workflow_runner.run()
# Contains all the ports of the inner workflow -> map back to the activity ports, and so we can set the correct
# Control ports to active and also set the data artefacts correctly
ports = extract_inner_workflow(workflow_model.odapi)
start_act = None
end_act = None
for port in [port for port in ports if port]:
port_name = workflow_model.odapi.get_name(port)
activity_port_name = get_activity_port_from_inner_port(composite_linkage[activity_name], port_name)
activity_port = od.get(activity_port_name)
match workflow_model.odapi.get_type_name(port):
case "pm_CtrlSource":
start_act = handle_control_source(od, activity_port, matched("prev_trace_element"))
case "pm_CtrlSink":
end_act = handle_control_sink(od, activity_port, start_act, matched("end_trace"))
case "pm_DataSource":
handle_data_source(od, activity_port, start_act)
case "pm_DataSink":
handle_data_sink(od, workflow_model.odapi, activity_port, port, end_act)
def handle_control_source(od: ODAPI, port, prev_trace_elem):
set_control_port_value(od, port, False)
start_activity = od.create_object(None, "pt_StartActivity")
create_activity_links(od, start_activity, prev_trace_elem, port)
return start_activity
def handle_control_sink(od: ODAPI, port, start_act, end_trace):
set_control_port_value(od, port, True)
end_activity = od.create_object(None, "pt_EndActivity")
create_activity_links(od, end_activity, start_act, port, end_trace)
return end_activity
def handle_data_source(od: ODAPI, port, start_activity):
pt_artefact = od.create_object(None, "pt_Artefact")
od.create_link(None, "pt_Consumes", pt_artefact, start_activity)
pm_artefact = get_source_incoming(od, port, "pm_DataFlowOut")
pm_artefact_data = get_artefact_data(od, pm_artefact)
set_artefact_data(od, pt_artefact, pm_artefact_data)
prev_pt_artefact = find_previous_artefact(od, od.get_incoming(pm_artefact, "pt_BelongsTo"))
if prev_pt_artefact:
od.create_link(None, "pt_PrevVersion", pt_artefact, prev_pt_artefact)
od.create_link(None, "pt_BelongsTo", pt_artefact, pm_artefact)
def handle_data_sink(act_od: ODAPI, work_od: ODAPI, act_port, work_port, end_activity):
pt_artefact = act_od.create_object(None, "pt_Artefact")
act_od.create_link(None, "pt_Produces", end_activity, pt_artefact)
work_artefact = get_source_incoming(work_od, work_port, "pm_DataFlowOut")
work_artefact_data = get_artefact_data(work_od, work_artefact)
act_artefact = get_target_outgoing(act_od, act_port, "pm_DataFlowIn")
set_artefact_data(act_od, act_artefact, work_artefact_data)
set_artefact_data(act_od, pt_artefact, work_artefact_data)
prev_pt_artefact = find_previous_artefact(act_od, act_od.get_incoming(act_artefact, "pt_BelongsTo"))
if prev_pt_artefact:
act_od.create_link(None, "pt_PrevVersion", pt_artefact, prev_pt_artefact)
act_od.create_link(None, "pt_BelongsTo", pt_artefact, act_artefact)
def extract_inner_workflow(workflow: ODAPI):
# Get the model, this should be only one
name, model = workflow.get_all_instances("pm_Model")[0]
# Get the start of the process trace
start_trace = get_source_incoming(workflow, model, "pt_Starts")
# Get the end of the process trace
end_trace = get_source_incoming(workflow, model, "pt_Ends")
# Get the first started activity
first_activity = get_target_outgoing(workflow, start_trace, "pt_IsFollowedBy")
# Get the last ended activity
end_activity = get_source_incoming(workflow, end_trace, "pt_IsFollowedBy")
# Get the control port that started the activity
act_ctrl_in = get_target_outgoing(workflow, first_activity, "pt_RelatesTo")
# Get the control port that is activated when the activity is executed
act_ctrl_out = get_target_outgoing(workflow, end_activity, "pt_RelatesTo")
# Get the control source of the workflow
ports = []
for port in workflow.get_incoming(act_ctrl_in, "pm_CtrlFlow"):
source = workflow.get_source(port)
if workflow.get_type_name(source) == "pm_CtrlSource":
# Only one port can activate an activity
ports.append(source)
break
# Get the control sink of the workflow
for port in workflow.get_outgoing(act_ctrl_out, "pm_CtrlFlow"):
sink = workflow.get_target(port)
if workflow.get_type_name(sink) == "pm_CtrlSink":
# Only one port can be set to active one an activity is ended
ports.append(sink)
break
# Get the data port that the activity consumes (if used)
consumed_links = workflow.get_incoming(first_activity, "pt_Consumes")
if len(consumed_links) > 0:
pt_artefact = None
for link in consumed_links:
pt_artefact = workflow.get_source(link)
# Check if it is the first artefact -> contains no previous version
if len(workflow.get_outgoing(pt_artefact, "pt_PrevVersion")) == 0:
break
pm_artefact = get_target_outgoing(workflow, pt_artefact, "pt_BelongsTo")
# Find the data source port
for link in workflow.get_incoming(pm_artefact, "pm_DataFlowIn"):
source = workflow.get_source(link)
if workflow.get_type_name(source) == "pm_DataSource":
# An activity can only use one artefact as input
ports.append(source)
break
# Get all data ports that are connected to an artefact that is produced by an activity in the workflow,
# where the artefact is also part of main workflow
for port_name, data_sink in workflow.get_all_instances("pm_DataSink"):
pm_art = get_source_incoming(workflow, data_sink, "pm_DataFlowOut")
# If the pm_artefact is linked to a proces trace artefact that is produced, we can add to port
links = workflow.get_incoming(pm_art, "pt_BelongsTo")
if not len(links):
continue
# A data sink port linkage will only be added to the proces trace when an activity is ended and so an artefact
# is produced, meaning that if a belongsTo link exists, a proces trace artefact is linked to this data port
ports.append(data_sink)
return ports

View file

@ -0,0 +1,2 @@
# Match the model
model:RAM_pm_Model

View file

@ -0,0 +1,7 @@
model:RAM_pm_Model
# Check if the model isn't already connected to a process trace
start_trace:RAM_pt_StartTrace
:RAM_pt_Starts (start_trace -> model)
end_trace:RAM_pt_EndTrace
:RAM_pt_Ends (end_trace -> model)

View file

@ -0,0 +1,12 @@
# Keep the left hand side
model:RAM_pm_Model
# Connect a process trace to it
start_trace:RAM_pt_StartTrace
starts:RAM_pt_Starts (start_trace -> model)
end_trace:RAM_pt_EndTrace
ends:RAM_pt_Ends (end_trace -> model)
# Connect the start with the end
:RAM_pt_IsFollowedBy (start_trace -> end_trace)

View file

@ -0,0 +1,49 @@
# When a control port is active and is connected to an activity, we want to execute the activity
# But, if the activity has input_and (input_or = False). It only can be activated if all its inputs are active
# Match the model
model:RAM_pm_Model
# Match the a python automated activity
py_activity:RAM_pm_PythonAutomatedActivity {
# Check if all connected ports are active in case of input_and
condition = ```
all_active = True
# Check for or / and
if not get_slot_value(this, "input_or"):
# Get all the ctrl in ports
for has_ctrl_in in get_outgoing(this, "pm_HasCtrlIn"):
c_in_state = get_source(get_incoming(get_target(has_ctrl_in), "pm_Of")[0])
# Check if the port is active or not
if not get_slot_value(c_in_state, "active"):
all_active = False
break
all_active
```;
} model_to_activity:RAM_pm_Owns (model -> py_activity)
# Match a control activity in port that is active
ctrl_in:RAM_pm_CtrlActivityIn
ctrl_in_state:RAM_pm_CtrlPortState {
RAM_active = `get_value(this)`;
}
state_to_port:RAM_pm_Of (ctrl_in_state -> ctrl_in)
# Match the activity link to the port
activity_to_port:RAM_pm_HasCtrlIn (py_activity -> ctrl_in)
# Match the end of the trace
end_trace:RAM_pt_EndTrace
ends:RAM_pt_Ends (end_trace -> model)
# Match the previous trace element before the end trace
prev_trace_element:RAM_pt_Event
followed_by:RAM_pt_IsFollowedBy (prev_trace_element -> end_trace)

View file

@ -0,0 +1,42 @@
model:RAM_pm_Model
py_activity:RAM_pm_PythonAutomatedActivity {
condition = ```
start_activity = create_object(None, "pt_StartActivity")
create_activity_links(odapi, start_activity, matched("prev_trace_element"), matched("ctrl_in"))
input_data = extract_input_data(odapi, this)
result = execute_activity(odapi, globals()["packages"], this, input_data)
if len(result) == 3:
status_code, output_data, input_used = result
else:
status_code, output_data, input_used = *result, None
if input_used:
handle_artefact(odapi, start_activity, "pt_Artefact", "pt_Consumes", get(input_used), input_data[input_used], direction="DataFlowOut")
end_activity = create_object(None, "pt_EndActivity")
ctrl_out = get(status_code)
create_activity_links(odapi, end_activity, start_activity, ctrl_out, end_trace=matched("end_trace"))
if output_data:
port, data = output_data
handle_artefact(odapi, end_activity, "pt_Artefact", "pt_Produces", get(port), data, direction="DataFlowIn")
update_control_states(odapi, this, ctrl_out)
```;
}
model_to_activity:RAM_pm_Owns
ctrl_in:RAM_pm_CtrlActivityIn
ctrl_in_state:RAM_pm_CtrlPortState {
RAM_active = `False`;
}
state_to_port:RAM_pm_Of (ctrl_in_state -> ctrl_in)
activity_to_port:RAM_pm_HasCtrlIn (py_activity -> ctrl_in)
end_trace:RAM_pt_EndTrace
ends:RAM_pt_Ends (end_trace -> model)
prev_trace_element:RAM_pt_Event

View file

@ -0,0 +1,36 @@
# When a control port is active and is connected to an activity, we want to execute the activity. If it is a composite one, we execute the inner workflow of it
# But, if the activity has input_and (input_or = False). It only can be activated if all its inputs are active
# Match the model
model:RAM_pm_Model
# Match the a python automated activity
activity:RAM_pm_Activity {
RAM_composite = `True`;
} model_to_activity:RAM_pm_Owns (model -> activity)
# Match a control activity in port that is active
ctrl_in:RAM_pm_CtrlActivityIn
ctrl_in_state:RAM_pm_CtrlPortState {
RAM_active = `get_value(this)`;
}
state_to_port:RAM_pm_Of (ctrl_in_state -> ctrl_in)
# Match the activity link to the port
activity_to_port:RAM_pm_HasCtrlIn (activity -> ctrl_in)
# Match the end of the trace
end_trace:RAM_pt_EndTrace
ends:RAM_pt_Ends (end_trace -> model)
# Match the previous trace element before the end trace
prev_trace_element:RAM_pt_Event
followed_by:RAM_pt_IsFollowedBy (prev_trace_element -> end_trace)

View file

@ -0,0 +1,29 @@
model:RAM_pm_Model
activity:RAM_pm_Activity {
RAM_composite = `True`;
condition = ```
# Execute inner workflow
execute_composite_workflow(odapi, this, matched("ctrl_in"), globals()["composite_linkage"], globals()["packages"], matched)
```;
}
model_to_activity:RAM_pm_Owns
ctrl_in:RAM_pm_CtrlActivityIn
ctrl_in_state:RAM_pm_CtrlPortState {
RAM_active = `False`;
}
state_to_port:RAM_pm_Of (ctrl_in_state -> ctrl_in)
activity_to_port:RAM_pm_HasCtrlIn (activity -> ctrl_in)
end_trace:RAM_pt_EndTrace
ends:RAM_pt_Ends (end_trace -> model)
prev_trace_element:RAM_pt_Event

View file

@ -0,0 +1,20 @@
# Match an active control output port
out_state:RAM_pm_CtrlPortState {
RAM_active = `get_value(this)`;
}
out:RAM_pm_CtrlOut
state_to_out:RAM_pm_Of (out_state -> out)
# Match an inactive control input port
in_state:RAM_pm_CtrlPortState {
RAM_active = `not get_value(this)`;
}
in:RAM_pm_CtrlIn
state_to_in:RAM_pm_Of (in_state -> in)
# Match the connection between those two ports
flow:RAM_pm_CtrlFlow (out -> in)

View file

@ -0,0 +1,42 @@
# Copy the left hand side
out_state:RAM_pm_CtrlPortState {
# Only set the output port to inactive if all connected input ports are set to active
RAM_active = ```
set_to_active = False
output_port = matched("out")
outgoing_flows = get_outgoing(output_port, "pm_CtrlFlow")
# for each flow: pm_CtrlFlow -> pm_CtrlIn <- pm_Of <- pm_CtrlPortState == state
all_input_port_states = [get_source(get_incoming(get_target(flow), "pm_Of")[0]) for flow in outgoing_flows]
input_port_state = matched("in_state")
for state in all_input_port_states:
is_active = get_slot_value(state, "active")
# If the state is not active and it is not the input port state we have matched and planned to set active
# Then we can't yet set this output port state to active
if not is_active and state != input_port_state:
set_to_active = True
break
# Set the attribute to the assigned value
set_to_active
```;
}
out:RAM_pm_CtrlOut
state_to_out:RAM_pm_Of (out_state -> out)
in_state:RAM_pm_CtrlPortState {
# Set the input port active
RAM_active = `True`;
}
in:RAM_pm_CtrlIn
state_to_in:RAM_pm_Of (in_state -> in)
flow:RAM_pm_CtrlFlow (out -> in)

View file

@ -0,0 +1,200 @@
##################################################
pm_Model:Class
##################################################
pm_Stateful:Class
##################################################
pm_ModelElement:Class {
abstract = True;
}
##################################################
pm_Activity:Class
:Inheritance (pm_Activity -> pm_ModelElement)
pm_Activity_name:AttributeLink (pm_Activity -> String) {
name = "name";
optional = False;
}
pm_Activity_composite:AttributeLink (pm_Activity -> Boolean) {
name = "composite";
optional = False;
}
pm_Activity_subworkflow_path:AttributeLink (pm_Activity -> String) {
name = "subworkflow_path";
optional = True;
}
pm_AutomatedActivity:Class {
abstract = True;
} :Inheritance (pm_AutomatedActivity -> pm_Activity)
pm_AutomatedActivity_input_or:AttributeLink (pm_AutomatedActivity -> Boolean) {
name = "input_or";
optional = False;
}
pm_PythonAutomatedActivity:Class
:Inheritance (pm_PythonAutomatedActivity -> pm_AutomatedActivity)
pm_PythonAutomatedActivity_func:AttributeLink (pm_PythonAutomatedActivity -> ActionCode) {
name = "func";
optional = False;
}
##################################################
pm_Artefact:Class
:Inheritance (pm_Artefact -> pm_ModelElement)
:Inheritance (pm_Artefact -> pm_Stateful)
##################################################
pm_CtrlPort:Class {
abstract = True;
} :Inheritance (pm_CtrlPort -> pm_Stateful)
pm_CtrlIn:Class {
abstract = True;
} :Inheritance (pm_CtrlIn -> pm_CtrlPort)
pm_CtrlSink:Class {
# 1) A control sink port must have at least one incoming control flow
# 2) A control sink port can't have any control flow output
constraint = ```
has_incoming = len(get_incoming(this, "pm_CtrlFlow")) > 0
no_outgoing = len(get_outgoing(this, "pm_CtrlFlow")) == 0
# Return constraint
has_incoming and no_outgoing
```;
} :Inheritance (pm_CtrlSink -> pm_CtrlIn)
pm_CtrlActivityIn:Class {
# 1) Must have at least one incoming control flow
constraint = ```
has_incoming = len(get_incoming(this, "pm_CtrlFlow")) > 0
# Return constraint
has_incoming
```;
} :Inheritance (pm_CtrlActivityIn -> pm_CtrlIn)
pm_CtrlOut:Class {
abstract = True;
} :Inheritance (pm_CtrlOut -> pm_CtrlPort)
pm_CtrlSource:Class {
# 1) A control source port can't have any control flow inputs
# 2) A control source port must have at least one outgoing control flow
constraint = ```
no_incoming = len(get_incoming(this, "pm_CtrlFlow")) == 0
has_outgoing = len(get_outgoing(this, "pm_CtrlFlow")) > 0
# Return constraint
no_incoming and has_outgoing
```;
} :Inheritance (pm_CtrlSource -> pm_CtrlOut)
pm_CtrlActivityOut:Class {
# 1) Must have at least one outgoing control flow
constraint = ```
has_outgoing = len(get_outgoing(this, "pm_CtrlFlow")) > 0
# Return constraint
has_outgoing
```;
} :Inheritance (pm_CtrlActivityOut -> pm_CtrlOut)
##################################################
pm_DataPort:Class {
abstract = True;
}
pm_DataIn:Class {
abstract = True;
} :Inheritance (pm_DataIn -> pm_DataPort)
pm_DataSink:Class
:Inheritance (pm_DataSink -> pm_DataIn)
pm_DataActivityIn:Class
:Inheritance (pm_DataActivityIn -> pm_DataIn)
pm_DataOut:Class {
abstract = True;
} :Inheritance (pm_DataOut -> pm_DataPort)
pm_DataSource:Class
:Inheritance (pm_DataSource -> pm_DataOut)
pm_DataActivityOut:Class
:Inheritance (pm_DataActivityOut -> pm_DataOut)
##################################################
##################################################
pm_Owns:Association (pm_Model -> pm_ModelElement) {
source_lower_cardinality = 1;
source_upper_cardinality = 1;
}
##################################################
pm_CtrlFlow:Association (pm_CtrlPort -> pm_CtrlPort)
##################################################
pm_HasCtrlIn:Association (pm_Activity -> pm_CtrlIn) {
source_upper_cardinality = 1;
target_lower_cardinality = 1;
}
pm_HasCtrlOut:Association (pm_Activity -> pm_CtrlOut) {
source_upper_cardinality = 1;
target_lower_cardinality = 1;
}
pm_HasDataIn:Association (pm_Activity -> pm_DataIn) {
source_upper_cardinality = 1;
}
pm_HasDataOut:Association (pm_Activity -> pm_DataOut) {
source_upper_cardinality = 1;
}
##################################################
pm_DataFlowIn:Association (pm_DataOut -> pm_Artefact) {
source_lower_cardinality = 1;
target_lower_cardinality = 1;
}
pm_DataFlowOut:Association (pm_Artefact -> pm_DataIn) {
source_lower_cardinality = 1;
target_lower_cardinality = 1;
}
##################################################
##################################################
has_source_and_sink:GlobalConstraint {
# There should be at least one source and sink control port
constraint = ```
contains_source = len(get_all_instances("pm_CtrlSource")) > 0
contains_sink = len(get_all_instances("pm_CtrlSink")) > 0
# return constraint
contains_source and contains_sink
```;
}
##################################################

View file

@ -0,0 +1,38 @@
##################################################
pm_State:Class {
abstract = True;
}
##################################################
pm_ArtefactState:Class
:Inheritance (pm_ArtefactState -> pm_State)
pm_ArtefactState_data:AttributeLink (pm_ArtefactState -> Bytes) {
name = "data";
optional = False;
}
##################################################
pm_CtrlPortState:Class
:Inheritance (pm_CtrlPortState -> pm_State)
pm_CtrlPortState_active:AttributeLink (pm_CtrlPortState -> Boolean) {
name = "active";
optional = False;
}
##################################################
##################################################
pm_Of:Association (pm_State -> pm_Stateful) {
# one-to-one
source_lower_cardinality = 1;
source_upper_cardinality = 1;
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}
##################################################

View file

@ -0,0 +1,109 @@
##################################################
pt_Event:Class {
abstract = True;
}
##################################################
pt_Activity:Class {
abstract = True;
} :Inheritance (pt_Activity -> pt_Event)
pt_StartActivity:Class {
# A start activity can only be related to a control in port
constraint = ```
correct_related = True
port = get_target(get_outgoing(this, "pt_RelatesTo")[0])
correct_related = port in [uid for _, uid in get_all_instances("pm_CtrlIn")]
correct_related
```;
} :Inheritance (pt_StartActivity -> pt_Activity)
pt_EndActivity:Class {
# A end activity can only be related to a control out port
constraint = ```
correct_related = True
port = get_target(get_outgoing(this, "pt_RelatesTo")[0])
correct_related = port in [uid for _, uid in get_all_instances("pm_CtrlOut")]
correct_related
```;
} :Inheritance (pt_EndActivity -> pt_Activity)
##################################################
pt_StartTrace:Class
:Inheritance (pt_StartTrace -> pt_Event)
pt_EndTrace:Class
:Inheritance (pt_EndTrace -> pt_Event)
##################################################
pt_Artefact:Class
:Inheritance (pt_Artefact -> pt_Event)
pt_Artefact_data:AttributeLink (pt_Artefact -> Bytes) {
name = "data";
optional = False;
}
##################################################
##################################################
pt_IsFollowedBy:Association (pt_Event -> pt_Event) {
source_upper_cardinality = 1;
target_upper_cardinality = 1;
}
##################################################
pt_RelatesTo:Association (pt_Activity -> pm_CtrlPort) {
source_upper_cardinality = 1;
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}
pt_Consumes:Association (pt_Artefact -> pt_StartActivity) {
source_upper_cardinality = 1;
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}
pt_Produces:Association (pt_EndActivity -> pt_Artefact) {
source_lower_cardinality = 1;
source_upper_cardinality = 1;
target_upper_cardinality = 1;
}
##################################################
pt_Starts:Association (pt_StartTrace -> pm_Model) {
source_upper_cardinality = 1;
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}
pt_Ends:Association (pt_EndTrace -> pm_Model) {
source_upper_cardinality = 1;
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}
##################################################
pt_PrevVersion:Association (pt_Artefact -> pt_Artefact) {
source_upper_cardinality = 1;
target_upper_cardinality = 1;
}
pt_BelongsTo:Association (pt_Artefact -> pm_Artefact) {
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}
##################################################

View file

@ -0,0 +1,162 @@
import re
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from util import loader
from transformation.rule import RuleMatcherRewriter
from transformation.ramify import ramify
from concrete_syntax.graphviz import renderer as graphviz
from concrete_syntax.graphviz.make_url import make_url
from concrete_syntax.plantuml import renderer as plantuml
from concrete_syntax.plantuml.make_url import make_url as plant_make_url
from api.od import ODAPI
import os
from os import listdir
from os.path import isfile, join
import importlib.util
from util.module_to_dict import module_to_dict
from examples.ftg_pm_pt import help_functions
from examples.ftg_pm_pt.ftg_pm_pt import FtgPmPt
class FtgPmPtRunner:
def __init__(self, model: FtgPmPt, composite_linkage: dict | None = None):
self.model = model
self.ram_mm = ramify(self.model.state, self.model.meta_model)
self.rules = self.load_rules()
self.packages = None
self.composite_linkage = composite_linkage
def load_rules(self):
return loader.load_rules(
self.model.state,
lambda rule_name, kind: os.path.join(
os.path.dirname(__file__),
f"operational_semantics/r_{rule_name}_{kind}.od"
),
self.ram_mm,
["connect_process_trace", "trigger_ctrl_flow", "exec_activity", "exec_composite_activity"]
)
def set_packages(self, packages: str | dict, is_path: bool):
if not is_path:
self.packages = packages
return
self.packages = self.parse_packages(packages)
def parse_packages(self, packages_path: str) -> dict:
return self.collect_functions_from_packages(packages_path, packages_path)
def collect_functions_from_packages(self, base_path, current_path):
functions_dict = {}
for entry in listdir(current_path):
entry_path = join(current_path, entry)
if isfile(entry_path) and entry.endswith(".py"):
module_name = self.convert_path_to_module_name(base_path, entry_path)
module = self.load_module_from_file(entry_path)
for func_name, func in module_to_dict(module).items():
functions_dict[f"{module_name}.{func_name}"] = func
elif not isfile(entry_path):
nested_functions = self.collect_functions_from_packages(base_path, entry_path)
functions_dict.update(nested_functions)
return functions_dict
@staticmethod
def convert_path_to_module_name(base_path, file_path):
return file_path.replace(base_path, "").replace(".py", "").replace("/", "")
@staticmethod
def load_module_from_file(file_path):
spec = importlib.util.spec_from_file_location("", file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def create_matcher(self):
packages = module_to_dict(help_functions)
if self.packages:
packages.update({ "packages": self.packages })
if self.composite_linkage:
packages.update({ "composite_linkage": self.composite_linkage })
matcher_rewriter = RuleMatcherRewriter(
self.model.state, self.model.meta_model, self.ram_mm, eval_context=packages
)
return matcher_rewriter
def visualize_model(self):
print(make_url(graphviz.render_object_diagram(self.model.state, self.model.model, self.model.meta_model)))
print(plant_make_url(plantuml.render_object_diagram(self.model.state, self.model.model, self.model.meta_model)))
@staticmethod
def __extract_artefact_info(od, pt_art):
"""Extract artefact metadata and data."""
data = od.get_slot_value(pt_art, "data")
pm_art = od.get_name(od.get_target(od.get_outgoing(pt_art, "pt_BelongsTo")[0]))
has_prev_version = bool(od.get_outgoing(pt_art, "pt_PrevVersion"))
is_last_version = not od.get_incoming(pt_art, "pt_PrevVersion")
return {
"Artefact Name": pm_art,
"Data": data,
"Has previous version": has_prev_version,
"Is last version": is_last_version
}
def __extract_inputs(self, od, event_node):
"""Extract all consumed artefacts for an event."""
return [
self.__extract_artefact_info(od, od.get_source(consumes))
for consumes in od.get_incoming(event_node, "pt_Consumes")
]
def __extract_outputs(self, od, event_node):
"""Extract all produced artefacts for an event."""
return [
self.__extract_artefact_info(od, od.get_target(produces))
for produces in od.get_outgoing(event_node, "pt_Produces")
]
@staticmethod
def to_snake_case(experiment_type):
# Finds uppercase letters that are not at the start of the string.
# Example: AtomicExperiment -> atomic_experiment
return re.sub(r'(?<!^)(?=[A-Z])', '_', experiment_type).lower()
def run(self, debug_flag: bool = False):
matcher = self.create_matcher()
rule_performed = True
while rule_performed:
# Loop over all the rules first in order priority
for i, (rule_name, rule) in enumerate(self.rules.items()):
rule_performed = False
result = matcher.exec_on_first_match(
self.model.model, rule, rule_name, in_place=True
)
# If the rule cannot be executed go to the next rule
if not result:
continue
rule_performed = True
self.model.model, lhs_match, _ = result
if debug_flag:
print(f"Match: {lhs_match}")
self.visualize_model()
# If a rule is performed, break and start loping over the rules from the beginning
break

View file

@ -0,0 +1,34 @@
digraph G {
rankdir=LR;
center=true;
margin=1;
nodesep=1;
node [fontname="Arial", fontsize=10, shape=box, style=filled, fillcolor=white];
// Geraniums
{% for id, name, flowering in geraniums %}
g{{ id }} [
label="geranium: {{ name }}\n({{ 'flowering' if flowering else 'not flowering' }})",
shape=ellipse,
fillcolor="{{ 'lightpink' if flowering else 'lightgray' }}",
fontcolor=black
];
{% endfor %}
// Pots
{% for id, name, cracked in pots %}
p{{ id }} [
label="pot: {{ name }}\n({{ 'cracked' if cracked else 'pristine' }})",
shape=box,
fillcolor="{{ 'mistyrose' if cracked else 'lightgreen' }}",
fontcolor=black,
style="filled,bold"
];
{% endfor %}
// Connections: geranium -> pot
{% for source, target in planted %}
g{{ source }} -> p{{ target }};
{% endfor %}
}

View file

@ -0,0 +1,9 @@
class Geranium {
Boolean flowering;
}
class Pot {
Boolean cracked;
}
association Planted [0..*] Geranium -> Pot [1..1]

View file

@ -0,0 +1,44 @@
import os
from jinja2 import Environment, FileSystemLoader
from api.od import ODAPI
from framework.conformance import eval_context_decorator
@eval_context_decorator
def _render_geraniums_dot(od: ODAPI, file: str) -> str:
__DIR__ = os.path.dirname(__file__)
env = Environment(
loader=FileSystemLoader(
__DIR__
)
)
env.trim_blocks = True
env.lstrip_blocks = True
template_dot = env.get_template("geraniums_renderer.j2")
id_count = 0
id_map = {}
render = {"geraniums": [], "pots": [], "planted": []}
for name, uuid in od.get_all_instances("Geranium"):
render["geraniums"].append((id_count, name, od.get_slot_value(uuid, "flowering")))
id_map[uuid] = id_count
id_count += 1
for name, uuid in od.get_all_instances("Pot"):
render["pots"].append((id_count, name, od.get_slot_value(uuid, "cracked")))
id_map[uuid] = id_count
id_count += 1
for name, uuid in od.get_all_instances("Planted"):
render["planted"].append((id_map[od.get_source(uuid)], id_map[od.get_target(uuid)]))
with open(file, "w", encoding="utf-8") as f_dot:
f_dot.write(template_dot.render(**render))
return ""
eval_context = {
"render_geraniums_dot": _render_geraniums_dot,
}

View file

@ -0,0 +1,17 @@
f1:Geranium {
flowering = True;
}
f2:Geranium {
flowering = False;
}
f3:Geranium {
flowering = True;
}
p1:Pot {
cracked = True;
}
:Planted (f1 -> p1)
:Planted (f2 -> p1)
:Planted (f3 -> p1)

View file

@ -0,0 +1,47 @@
f1:Geranium {
flowering = True;
}
f2:Geranium {
flowering = True;
}
f3:Geranium {
flowering = False;
}
p1:Pot {
cracked = True;
}
:Planted (f1 -> p1)
:Planted (f2 -> p1)
:Planted (f3 -> p1)
f4:Geranium {
flowering = True;
}
p2:Pot {
cracked = True;
}
:Planted (f4 -> p2)
f5:Geranium {
flowering = True;
}
p3:Pot {
cracked = False;
}
:Planted (f5 -> p3)
f6:Geranium {
flowering = False;
}
p4:Pot {
cracked = True;
}
:Planted (f6 -> p4)

View file

@ -0,0 +1,45 @@
import os
from jinja2 import Environment, FileSystemLoader
from api.od import ODAPI
from concrete_syntax.graphviz.make_url import show_graphviz
from concrete_syntax.graphviz.renderer import make_graphviz_id
try:
import graphviz
HAVE_GRAPHVIZ = True
except ImportError:
HAVE_GRAPHVIZ = False
def render_geraniums_dot(od: ODAPI, file: str) -> str:
__DIR__ = os.path.dirname(__file__)
env = Environment(
loader=FileSystemLoader(
__DIR__
)
)
env.trim_blocks = True
env.lstrip_blocks = True
template_dot = env.get_template("geraniums_renderer.j2")
id_count = 0
id_map = {}
render = {"geraniums": [], "pots": [], "planted": []}
for name, uuid in od.get_all_instances("Geranium"):
render["geraniums"].append((id_count, name, od.get_slot_value(uuid, "flowering")))
id_map[uuid] = id_count
id_count += 1
for name, uuid in od.get_all_instances("Pot"):
render["pots"].append((id_count, name, od.get_slot_value(uuid, "cracked")))
id_map[uuid] = id_count
id_count += 1
for name, uuid in od.get_all_instances("Planted"):
render["planted"].append((id_map[od.get_source(uuid)], id_map[od.get_target(uuid)]))
with open(file, "w", encoding="utf-8") as f_dot:
f_dot.write(template_dot.render(**render))
return ""

View file

@ -0,0 +1,3 @@
pot:RAM_Pot {
RAM_cracked = `get_value(this)`;
}

View file

@ -0,0 +1,3 @@
pot:RAM_Pot {
RAM_cracked = `False`;
}

View file

@ -0,0 +1,7 @@
pot:RAM_Pot
flower:RAM_Geranium {
RAM_flowering = `get_value(this)`;
}
:RAM_Planted (flower -> pot)

View file

@ -0,0 +1,8 @@
pot:RAM_Pot
new_pot:RAM_Pot
flower:RAM_Geranium {
RAM_flowering = `get_value(this)`;
}
replant:RAM_Planted (flower -> new_pot)

View file

@ -0,0 +1,48 @@
from examples.geraniums.renderer import render_geraniums_dot
from transformation.ramify import ramify
from models.eval_context import eval_context
from transformation.schedule.rule_scheduler import *
if __name__ == "__main__":
import os
THIS_DIR = os.path.dirname(__file__)
# get file contents as string
def read_file(filename):
with open(THIS_DIR+'/'+filename) as file:
return file.read()
state = DevState()
scd_mmm = bootstrap_scd(state)
mm_cs = read_file('metamodels/mm.od')
m_cs = read_file('models/example2.od')
mm = parser_cd.parse_cd(
state,
m_text=mm_cs,
)
m = parser_od.parse_od(
state, m_text=m_cs, mm=mm
)
conf_err = Conformance(
state, m, mm
).check_nominal()
print(render_conformance_check_result(conf_err))
mm_ramified = ramify(state, mm)
action_generator = RuleScheduler(state, mm, mm_ramified, verbose=True, directory="examples/geraniums", eval_context=eval_context)
od = ODAPI(state, m, mm)
render_geraniums_dot(od, f"{THIS_DIR}/geraniums.dot")
# if action_generator.load_schedule(f"petrinet.od"):
# if action_generator.load_schedule("schedules/combinatory.drawio"):
if action_generator.load_schedule("schedules/schedule.drawio"):
action_generator.generate_dot("../dot.dot")
code, message = action_generator.run(od)
print(f"{code}: {message}")
render_geraniums_dot(od, f"{THIS_DIR}/geraniums_final.dot")

View file

@ -0,0 +1,645 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.5 Chrome/134.0.6998.205 Electron/35.3.0 Safari/537.36" version="27.0.5" pages="2">
<diagram name="main" id="pASKGN4qU69vjyreTE56">
<mxGraphModel dx="1389" dy="835" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="start" type="Start" ports_exec_out="[&quot;out&quot;]" ports_data_out="[]" id="cchbAGZklJLD93cgxIrT-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="80" y="110" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="cchbAGZklJLD93cgxIrT-1" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-2" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-2" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="cchbAGZklJLD93cgxIrT-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%&#xa;%file%&#xa;matches: %n%" placeholders="1" name="cracked pots" type="Match" file="rules/cracked_pots.od" n="" id="cchbAGZklJLD93cgxIrT-6">
<mxCell style="shape=table;childLayout=tableLayout;startSize=60;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="280" y="90" width="160" height="220" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-7" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="cchbAGZklJLD93cgxIrT-6" vertex="1">
<mxGeometry y="60" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-8" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-7" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="cchbAGZklJLD93cgxIrT-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-8" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="cchbAGZklJLD93cgxIrT-10">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-8" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-11" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-7" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="cchbAGZklJLD93cgxIrT-12">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-11" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="success" type="exec" id="cchbAGZklJLD93cgxIrT-13">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-11" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="fail" type="exec" id="cchbAGZklJLD93cgxIrT-14">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-11" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="cchbAGZklJLD93cgxIrT-5" target="cchbAGZklJLD93cgxIrT-10" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%" placeholders="1" name="end" type="End" ports_exec_in="[&quot;in&quot;]" ports_data_in="[]" id="cchbAGZklJLD93cgxIrT-24">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="520" y="350" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-25" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="cchbAGZklJLD93cgxIrT-24" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-26" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-25" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="cchbAGZklJLD93cgxIrT-27">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-26" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-28" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-25" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="cchbAGZklJLD93cgxIrT-14" target="cchbAGZklJLD93cgxIrT-27" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="500" y="230" />
<mxPoint x="500" y="420" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="remove cracked status&#xa;" type="Modify" rename="{}" delete="[&quot;pot_RAM_cracked&quot;, &quot;pot.RAM_cracked&quot;]" id="cchbAGZklJLD93cgxIrT-32">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="270" y="350" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-33" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="cchbAGZklJLD93cgxIrT-32" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-34" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-33" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="cchbAGZklJLD93cgxIrT-35">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-34" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-36" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-33" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="cchbAGZklJLD93cgxIrT-37">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-36" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="cchbAGZklJLD93cgxIrT-12" target="cchbAGZklJLD93cgxIrT-35" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="460" y="280" />
<mxPoint x="460" y="330" />
<mxPoint x="250" y="330" />
<mxPoint x="250" y="420" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%&#xa;%file%&#xa;matches: %n%" placeholders="1" name="flowering flower" type="Match" file="rules/flowering_flowers_in_pot.od" n="" id="cchbAGZklJLD93cgxIrT-41">
<mxCell style="shape=table;childLayout=tableLayout;startSize=60;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="760" y="40" width="160" height="220" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-42" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="cchbAGZklJLD93cgxIrT-41" vertex="1">
<mxGeometry y="60" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-43" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-42" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="cchbAGZklJLD93cgxIrT-44">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-43" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="cchbAGZklJLD93cgxIrT-45">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-43" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-46" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-42" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="cchbAGZklJLD93cgxIrT-47">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-46" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="success" type="exec" id="cchbAGZklJLD93cgxIrT-48">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-46" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="fail" type="exec" id="cchbAGZklJLD93cgxIrT-49">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-46" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="iterate pots" type="Loop" id="cchbAGZklJLD93cgxIrT-53">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="520" y="110" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-54" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="cchbAGZklJLD93cgxIrT-53" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-55" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-54" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="cchbAGZklJLD93cgxIrT-56">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-55" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="cchbAGZklJLD93cgxIrT-57">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-55" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-58" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="cchbAGZklJLD93cgxIrT-54" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="cchbAGZklJLD93cgxIrT-59">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="cchbAGZklJLD93cgxIrT-58" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="it" type="exec" id="cchbAGZklJLD93cgxIrT-60">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-58" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="exec" id="cchbAGZklJLD93cgxIrT-61">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="cchbAGZklJLD93cgxIrT-58" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="cchbAGZklJLD93cgxIrT-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="cchbAGZklJLD93cgxIrT-13" target="cchbAGZklJLD93cgxIrT-57" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="460" y="180" />
<mxPoint x="460" y="180" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="cchbAGZklJLD93cgxIrT-37" target="cchbAGZklJLD93cgxIrT-56" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="480" y="420" />
<mxPoint x="480" y="280" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="cchbAGZklJLD93cgxIrT-60" target="cchbAGZklJLD93cgxIrT-45" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cchbAGZklJLD93cgxIrT-84" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="cchbAGZklJLD93cgxIrT-49" target="cchbAGZklJLD93cgxIrT-57" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="940" y="180" />
<mxPoint x="940" y="20" />
<mxPoint x="500" y="20" />
<mxPoint x="500" y="180" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="repot flowers" type="Schedule" file="repot_flowers" id="COygDAZokINshI2ZcMDj-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="980" y="60" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="COygDAZokINshI2ZcMDj-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="COygDAZokINshI2ZcMDj-1" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="COygDAZokINshI2ZcMDj-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="COygDAZokINshI2ZcMDj-2" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="COygDAZokINshI2ZcMDj-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="COygDAZokINshI2ZcMDj-3" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="flowers" type="data" id="OE_qcAbxz6Js6tdFO397-1">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="COygDAZokINshI2ZcMDj-3" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="COygDAZokINshI2ZcMDj-5" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="COygDAZokINshI2ZcMDj-2" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="COygDAZokINshI2ZcMDj-6">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="COygDAZokINshI2ZcMDj-5" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="OE_qcAbxz6Js6tdFO397-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="cchbAGZklJLD93cgxIrT-47" target="OE_qcAbxz6Js6tdFO397-1" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="960" y="230" />
<mxPoint x="960" y="180" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="OE_qcAbxz6Js6tdFO397-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="cchbAGZklJLD93cgxIrT-48" target="COygDAZokINshI2ZcMDj-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OE_qcAbxz6Js6tdFO397-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="COygDAZokINshI2ZcMDj-6" target="cchbAGZklJLD93cgxIrT-57" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1200" y="130" />
<mxPoint x="1200" y="20" />
<mxPoint x="500" y="20" />
<mxPoint x="500" y="180" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="EqK5vrE8kE92bJcIEnmP-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="cchbAGZklJLD93cgxIrT-61" target="cchbAGZklJLD93cgxIrT-27" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="720" y="230" />
<mxPoint x="720" y="330" />
<mxPoint x="500" y="330" />
<mxPoint x="500" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="tqyI29rS8I0LFEd-KlyY-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" edge="1" parent="1" source="cchbAGZklJLD93cgxIrT-59" target="cchbAGZklJLD93cgxIrT-44">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="740" y="280" />
<mxPoint x="740" y="230" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="c3Tuc6LHjhM7aXRdpPRx" name="repot_flowers">
<mxGraphModel dx="1042" dy="626" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="start_repotting" type="Start" ports_exec_out="[&quot;out&quot;]" ports_data_out="[&quot;flowers&quot;, &quot;old_pot&quot;]" id="gjxSdUMfFO3v8k7oyOzM-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="80" y="240" width="160" height="160" as="geometry" />
</mxCell>
</object>
<mxCell id="gjxSdUMfFO3v8k7oyOzM-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="gjxSdUMfFO3v8k7oyOzM-1" vertex="1">
<mxGeometry y="40" width="160" height="120" as="geometry" />
</mxCell>
<mxCell id="gjxSdUMfFO3v8k7oyOzM-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="gjxSdUMfFO3v8k7oyOzM-2" vertex="1">
<mxGeometry width="80" height="120" as="geometry">
<mxRectangle width="80" height="120" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gjxSdUMfFO3v8k7oyOzM-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="gjxSdUMfFO3v8k7oyOzM-2" vertex="1">
<mxGeometry x="80" width="80" height="120" as="geometry">
<mxRectangle width="80" height="120" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="gjxSdUMfFO3v8k7oyOzM-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="gjxSdUMfFO3v8k7oyOzM-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="flowers" type="data" id="gjxSdUMfFO3v8k7oyOzM-6">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="gjxSdUMfFO3v8k7oyOzM-4" vertex="1">
<mxGeometry x="10" y="70" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="end" type="End" ports_exec_in="[&quot;in&quot;]" ports_data_in="[]" id="gjxSdUMfFO3v8k7oyOzM-8">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="740" y="410" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="gjxSdUMfFO3v8k7oyOzM-9" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="gjxSdUMfFO3v8k7oyOzM-8" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="gjxSdUMfFO3v8k7oyOzM-10" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="gjxSdUMfFO3v8k7oyOzM-9" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="gjxSdUMfFO3v8k7oyOzM-11">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="gjxSdUMfFO3v8k7oyOzM-10" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="gjxSdUMfFO3v8k7oyOzM-12" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="gjxSdUMfFO3v8k7oyOzM-9" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="iterate flowers" type="Loop" id="rgPZtlXADXUwMSGqODkz-8">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="500" y="240" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-9" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="rgPZtlXADXUwMSGqODkz-8" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="rgPZtlXADXUwMSGqODkz-10" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-9" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="rgPZtlXADXUwMSGqODkz-11">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-10" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="rgPZtlXADXUwMSGqODkz-12">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="rgPZtlXADXUwMSGqODkz-10" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-13" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-9" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="rgPZtlXADXUwMSGqODkz-14">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-13" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="it" type="exec" id="rgPZtlXADXUwMSGqODkz-15">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="rgPZtlXADXUwMSGqODkz-13" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="exec" id="rgPZtlXADXUwMSGqODkz-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="rgPZtlXADXUwMSGqODkz-13" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="create new pot" type="Rewrite" file="rules/create_pot.od" id="rgPZtlXADXUwMSGqODkz-17">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="280" y="240.0000000000001" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-18" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="rgPZtlXADXUwMSGqODkz-17" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="rgPZtlXADXUwMSGqODkz-19" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-18" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="rgPZtlXADXUwMSGqODkz-20">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="rgPZtlXADXUwMSGqODkz-19" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-21" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-18" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="rgPZtlXADXUwMSGqODkz-22">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="rgPZtlXADXUwMSGqODkz-21" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="data" id="rgPZtlXADXUwMSGqODkz-23">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-21" vertex="1">
<mxGeometry x="-70" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="data" id="rgPZtlXADXUwMSGqODkz-24">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-21" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="remove cracked status&#xa;" type="Modify" rename="{&quot;pot&quot;: &quot;new_pot&quot;}" delete="[&quot;pot_RAM_cracked&quot;, &quot;pot.RAM_cracked&quot;]" id="rgPZtlXADXUwMSGqODkz-32">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="280" y="450" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-33" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="rgPZtlXADXUwMSGqODkz-32" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="rgPZtlXADXUwMSGqODkz-34" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-33" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="rgPZtlXADXUwMSGqODkz-35">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-34" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-36" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-33" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="rgPZtlXADXUwMSGqODkz-37">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-36" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="gjxSdUMfFO3v8k7oyOzM-5" target="rgPZtlXADXUwMSGqODkz-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="rgPZtlXADXUwMSGqODkz-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="rgPZtlXADXUwMSGqODkz-24" target="rgPZtlXADXUwMSGqODkz-35" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="460" y="360" />
<mxPoint x="460" y="430" />
<mxPoint x="260" y="430" />
<mxPoint x="260" y="520" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="rgPZtlXADXUwMSGqODkz-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="gjxSdUMfFO3v8k7oyOzM-6" target="rgPZtlXADXUwMSGqODkz-11" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="260" y="370" />
<mxPoint x="260" y="410" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="combine new pot and flower&#xa;" type="Merge" ports_data_in="[&quot;flower&quot;, &quot;new_pot&quot;]" id="rgPZtlXADXUwMSGqODkz-43">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="500" y="480" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-44" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="rgPZtlXADXUwMSGqODkz-43" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="rgPZtlXADXUwMSGqODkz-45" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-44" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="flower" type="data" id="rgPZtlXADXUwMSGqODkz-46">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-45" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="new_pot" type="data" id="rgPZtlXADXUwMSGqODkz-47">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-45" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-48" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rgPZtlXADXUwMSGqODkz-44" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="rgPZtlXADXUwMSGqODkz-49">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rgPZtlXADXUwMSGqODkz-48" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rgPZtlXADXUwMSGqODkz-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="rgPZtlXADXUwMSGqODkz-14" target="rgPZtlXADXUwMSGqODkz-46" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="680" y="410" />
<mxPoint x="680" y="460" />
<mxPoint x="480" y="460" />
<mxPoint x="480" y="550" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="rgPZtlXADXUwMSGqODkz-60" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="rgPZtlXADXUwMSGqODkz-37" target="rgPZtlXADXUwMSGqODkz-47" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="460" y="520" />
<mxPoint x="460" y="600" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="move flower to new pot&#xa;" type="Rewrite" file="rules/repot_flower_in_pot.od" id="rggt9Ju99cdMwxSiOdaC-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="740" y="240.0000000000001" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="rggt9Ju99cdMwxSiOdaC-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="rggt9Ju99cdMwxSiOdaC-1" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="rggt9Ju99cdMwxSiOdaC-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rggt9Ju99cdMwxSiOdaC-2" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="rggt9Ju99cdMwxSiOdaC-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="rggt9Ju99cdMwxSiOdaC-3" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rggt9Ju99cdMwxSiOdaC-5" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="rggt9Ju99cdMwxSiOdaC-2" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="rggt9Ju99cdMwxSiOdaC-6">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="rggt9Ju99cdMwxSiOdaC-5" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="data" id="rggt9Ju99cdMwxSiOdaC-7">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rggt9Ju99cdMwxSiOdaC-5" vertex="1">
<mxGeometry x="-70" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="data" id="rggt9Ju99cdMwxSiOdaC-8">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="rggt9Ju99cdMwxSiOdaC-5" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="rggt9Ju99cdMwxSiOdaC-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="rgPZtlXADXUwMSGqODkz-15" target="rggt9Ju99cdMwxSiOdaC-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="rggt9Ju99cdMwxSiOdaC-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="rgPZtlXADXUwMSGqODkz-49" target="rggt9Ju99cdMwxSiOdaC-7" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="720" y="550" />
<mxPoint x="720" y="360" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="rggt9Ju99cdMwxSiOdaC-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="rggt9Ju99cdMwxSiOdaC-6" target="rgPZtlXADXUwMSGqODkz-12" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="920" y="310" />
<mxPoint x="920" y="220" />
<mxPoint x="480" y="220" />
<mxPoint x="480" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="rggt9Ju99cdMwxSiOdaC-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="rgPZtlXADXUwMSGqODkz-16" target="gjxSdUMfFO3v8k7oyOzM-11" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="700" y="360" />
<mxPoint x="700" y="480" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="nF2FpsghIUv3jzvNKQr9-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="rgPZtlXADXUwMSGqODkz-22" target="rgPZtlXADXUwMSGqODkz-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View file

@ -1,139 +0,0 @@
package "DSL Meta-Model" {
class "Bear" as 00000000_0000_0000_0000_00000000046d {
}
abstract class "Animal" as 00000000_0000_0000_0000_000000000474 {
}
class "Man" as 00000000_0000_0000_0000_000000000491 {
weight : Integer
}
00000000_0000_0000_0000_000000000474 <|-- 00000000_0000_0000_0000_000000000491
00000000_0000_0000_0000_000000000474 <|-- 00000000_0000_0000_0000_00000000046d
00000000_0000_0000_0000_000000000491 " " --> "1 .. *" 00000000_0000_0000_0000_000000000474 : afraidOf
}
package "Int Meta-Model" {
class "Integer" as 00000000_0000_0000_0000_000000000094 {
}
}
package "RAMified DSL Meta-Model" {
class "RAM_Bear" as 00000000_0000_0000_0000_0000000005bb {
}
class "RAM_Animal" as 00000000_0000_0000_0000_0000000005c5 {
}
class "RAM_Man" as 00000000_0000_0000_0000_0000000005cf {
RAM_weight : ActionCode
}
00000000_0000_0000_0000_0000000005c5 <|-- 00000000_0000_0000_0000_0000000005cf
00000000_0000_0000_0000_0000000005c5 <|-- 00000000_0000_0000_0000_0000000005bb
00000000_0000_0000_0000_0000000005cf " " --> "0 .. *" 00000000_0000_0000_0000_0000000005c5 : RAM_afraidOf
}
package "RAMified Int Meta-Model" {
class "RAM_Integer" as 00000000_0000_0000_0000_00000000064c {
}
}
00000000_0000_0000_0000_0000000005bb ..> 00000000_0000_0000_0000_00000000046d #line:green;text:green : RAMifies
00000000_0000_0000_0000_0000000005c5 ..> 00000000_0000_0000_0000_000000000474 #line:green;text:green : RAMifies
00000000_0000_0000_0000_0000000005cf ..> 00000000_0000_0000_0000_000000000491 #line:green;text:green : RAMifies
00000000_0000_0000_0000_0000000005cf::RAM_weight ..> 00000000_0000_0000_0000_000000000491::weight #line:green;text:green : RAMifies
00000000_0000_0000_0000_00000000064c ..> 00000000_0000_0000_0000_000000000094 #line:green;text:green : RAMifies
package "LHS" {
map "scaryAnimal : RAM_Animal" as 00000000_0000_0000_0000_00000000068a {
}
map "man : RAM_Man" as 00000000_0000_0000_0000_00000000066d {
RAM_weight => `v > 60`
}
00000000_0000_0000_0000_00000000066d -> 00000000_0000_0000_0000_00000000068a : :RAM_afraidOf
}
00000000_0000_0000_0000_00000000068a ..> 00000000_0000_0000_0000_0000000005c5 #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_00000000066d ..> 00000000_0000_0000_0000_0000000005cf #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_00000000066d::RAM_weight ..> 00000000_0000_0000_0000_0000000005cf::RAM_weight #line:blue;text:blue : instanceOf
package "RHS" {
map "man : RAM_Man" as 00000000_0000_0000_0000_000000000699 {
RAM_weight => `v + 5`
}
map "bill : RAM_Man" as 00000000_0000_0000_0000_0000000006b6 {
RAM_weight => `100`
}
00000000_0000_0000_0000_0000000006b6 -> 00000000_0000_0000_0000_000000000699 : :RAM_afraidOf
}
00000000_0000_0000_0000_000000000699 ..> 00000000_0000_0000_0000_0000000005cf #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000699::RAM_weight ..> 00000000_0000_0000_0000_0000000005cf::RAM_weight #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_0000000006b6 ..> 00000000_0000_0000_0000_0000000005cf #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_0000000006b6::RAM_weight ..> 00000000_0000_0000_0000_0000000005cf::RAM_weight #line:blue;text:blue : instanceOf
package "Model (before rewrite)" {
map "bear2 : Bear" as 00000000_0000_0000_0000_000000000597 {
}
map "bear1 : Bear" as 00000000_0000_0000_0000_000000000590 {
}
map "george : Man" as 00000000_0000_0000_0000_000000000573 {
weight => 80
}
00000000_0000_0000_0000_000000000573 -> 00000000_0000_0000_0000_000000000590 : :afraidOf
00000000_0000_0000_0000_000000000573 -> 00000000_0000_0000_0000_000000000597 : :afraidOf
}
00000000_0000_0000_0000_000000000597 ..> 00000000_0000_0000_0000_00000000046d #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000590 ..> 00000000_0000_0000_0000_00000000046d #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000573 ..> 00000000_0000_0000_0000_000000000491 #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000573::weight ..> 00000000_0000_0000_0000_000000000491::weight #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_00000000068a ..> 00000000_0000_0000_0000_000000000590 #line:red;line.dotted;text:red : matchedWith
00000000_0000_0000_0000_00000000066d ..> 00000000_0000_0000_0000_000000000573 #line:red;line.dotted;text:red : matchedWith
00000000_0000_0000_0000_00000000066d::RAM_weight ..> 00000000_0000_0000_0000_000000000573::weight #line:red;line.dotted;text:red : matchedWith
package "Model (after rewrite 0)" {
map "bear2 : Bear" as 00000000_0000_0000_0000_0000000006db {
}
map "george : Man" as 00000000_0000_0000_0000_0000000006e9 {
weight => 85
}
map "bill0 : Man" as 00000000_0000_0000_0000_000000000723 {
weight => 100
}
00000000_0000_0000_0000_000000000723 -> 00000000_0000_0000_0000_0000000006e9 : :afraidOf
00000000_0000_0000_0000_0000000006e9 -> 00000000_0000_0000_0000_0000000006db : :afraidOf
}
00000000_0000_0000_0000_000000000699 ..> 00000000_0000_0000_0000_0000000006e9 #line:red;line.dotted;text:red : matchedWith
00000000_0000_0000_0000_000000000699::RAM_weight ..> 00000000_0000_0000_0000_0000000006e9::weight #line:red;line.dotted;text:red : matchedWith
00000000_0000_0000_0000_0000000006b6 ..> 00000000_0000_0000_0000_000000000723 #line:red;line.dotted;text:red : matchedWith
00000000_0000_0000_0000_0000000006db ..> 00000000_0000_0000_0000_00000000046d #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_0000000006e9 ..> 00000000_0000_0000_0000_000000000491 #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_0000000006e9::weight ..> 00000000_0000_0000_0000_000000000491::weight #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000723 ..> 00000000_0000_0000_0000_000000000491 #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000723::weight ..> 00000000_0000_0000_0000_000000000491::weight #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_00000000068a ..> 00000000_0000_0000_0000_000000000597 #line:orange;line.dotted;text:orange : matchedWith
00000000_0000_0000_0000_00000000066d ..> 00000000_0000_0000_0000_000000000573 #line:orange;line.dotted;text:orange : matchedWith
00000000_0000_0000_0000_00000000066d::RAM_weight ..> 00000000_0000_0000_0000_000000000573::weight #line:orange;line.dotted;text:orange : matchedWith
package "Model (after rewrite 1)" {
map "bear1 : Bear" as 00000000_0000_0000_0000_000000000747 {
}
map "george : Man" as 00000000_0000_0000_0000_00000000074e {
weight => 85
}
map "bill0 : Man" as 00000000_0000_0000_0000_000000000788 {
weight => 100
}
00000000_0000_0000_0000_000000000788 -> 00000000_0000_0000_0000_00000000074e : :afraidOf
00000000_0000_0000_0000_00000000074e -> 00000000_0000_0000_0000_000000000747 : :afraidOf
}
00000000_0000_0000_0000_000000000699 ..> 00000000_0000_0000_0000_00000000074e #line:orange;line.dotted;text:orange : matchedWith
00000000_0000_0000_0000_000000000699::RAM_weight ..> 00000000_0000_0000_0000_00000000074e::weight #line:orange;line.dotted;text:orange : matchedWith
00000000_0000_0000_0000_0000000006b6 ..> 00000000_0000_0000_0000_000000000788 #line:orange;line.dotted;text:orange : matchedWith
00000000_0000_0000_0000_000000000747 ..> 00000000_0000_0000_0000_00000000046d #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_00000000074e ..> 00000000_0000_0000_0000_000000000491 #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_00000000074e::weight ..> 00000000_0000_0000_0000_000000000491::weight #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000788 ..> 00000000_0000_0000_0000_000000000491 #line:blue;text:blue : instanceOf
00000000_0000_0000_0000_000000000788::weight ..> 00000000_0000_0000_0000_000000000491::weight #line:blue;text:blue : instanceOf

View file

@ -1,245 +0,0 @@
# Model transformation experiment
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from uuid import UUID
from services.scd import SCD
from framework.conformance import Conformance
from services.od import OD
from transformation.matcher import match_od
from transformation.ramify import ramify
from transformation.cloner import clone_od
from transformation import rewriter
from services.bottom.V0 import Bottom
from services.primitives.integer_type import Integer
from concrete_syntax.plantuml import renderer as plantuml
from concrete_syntax.plantuml.make_url import make_url as make_plantuml_url
from concrete_syntax.textual_od import parser, renderer
def main():
state = DevState()
root = state.read_root() # id: 0
# Meta-meta-model: a class diagram that describes the language of class diagrams
scd_mmm_id = bootstrap_scd(state)
int_mm_id = UUID(state.read_value(state.read_dict(state.read_root(), "Integer")))
string_mm_id = UUID(state.read_value(state.read_dict(state.read_root(), "String")))
# conf = Conformance(state, scd_mmm_id, scd_mmm_id)
# print("Conformance SCD_MM -> SCD_MM?", conf.check_nominal(log=True))
# print("--------------------------------------")
# print(renderer.render_od(state, scd_mmm_id, scd_mmm_id, hide_names=True))
# print("--------------------------------------")
# Create DSL MM with parser
dsl_mm_cs = """
# Integer:ModelRef
Bear:Class
Animal:Class {
abstract = True;
}
Man:Class {
lower_cardinality = 1;
upper_cardinality = 2;
constraint = ```
get_value(get_slot(this, "weight")) > 20
```;
}
Man_weight:AttributeLink (Man -> Integer) {
name = "weight";
optional = False;
constraint = ```
# this is the same constraint as above, but this time, part of the attributelink itself (and thus shorter)
tgt = get_target(this)
tgt_type = get_type_name(tgt)
get_value(tgt) > 20
```;
}
afraidOf:Association (Man -> Animal) {
target_lower_cardinality = 1;
}
:Inheritance (Man -> Animal)
:Inheritance (Bear -> Animal)
not_too_fat:GlobalConstraint {
constraint = ```
# total weight of all men low enough
total_weight = 0
for man_name, man_id in get_all_instances("Man"):
total_weight += get_value(get_slot(man_id, "weight"))
total_weight < 85
```;
}
"""
dsl_mm_id = parser.parse_od(state, dsl_mm_cs, mm=scd_mmm_id)
# Create DSL M with parser
dsl_m_cs = """
george:Man {
weight = 80;
}
bear1:Bear
bear2:Bear
:afraidOf (george -> bear1)
:afraidOf (george -> bear2)
"""
dsl_m_id = parser.parse_od(state, dsl_m_cs, mm=dsl_mm_id)
# print("DSL MM:")
# print("--------------------------------------")
# print(renderer.render_od(state, dsl_mm_id, scd_mmm_id, hide_names=True))
# print("--------------------------------------")
conf = Conformance(state, dsl_mm_id, scd_mmm_id)
print("Conformance DSL_MM -> SCD_MM?", conf.check_nominal(log=True))
# print("DSL M:")
# print("--------------------------------------")
# print(renderer.render_od(state, dsl_m_id, dsl_mm_id, hide_names=True))
# print("--------------------------------------")
conf = Conformance(state, dsl_m_id, dsl_mm_id)
print("Conformance DSL_M -> DSL_MM?", conf.check_nominal(log=True))
# RAMify MM
prefix = "RAM_" # all ramified types can be prefixed to distinguish them a bit more
ramified_mm_id = ramify(state, dsl_mm_id, prefix)
ramified_int_mm_id = ramify(state, int_mm_id, prefix)
# LHS - pattern to match
# TODO: enable more powerful constraints
lhs_cs = f"""
# object to match
man:{prefix}Man {{
# match only men heavy enough
{prefix}weight = ```
get_value(this) > 60
```;
}}
# object to delete
scaryAnimal:{prefix}Animal
# link to delete
manAfraidOfAnimal:{prefix}afraidOf (man -> scaryAnimal)
"""
lhs_id = parser.parse_od(state, lhs_cs, mm=ramified_mm_id)
conf = Conformance(state, lhs_id, ramified_mm_id)
print("Conformance LHS_M -> RAM_DSL_MM?", conf.check_nominal(log=True))
# RHS of our rule
# TODO: enable more powerful actions
rhs_cs = f"""
# matched object
man:{prefix}Man {{
# man gains weight
{prefix}weight = `get_value(this) + 5`;
}}
# object to create
bill:{prefix}Man {{
{prefix}weight = `100`;
}}
# link to create
billAfraidOfMan:{prefix}afraidOf (bill -> man)
"""
rhs_id = parser.parse_od(state, rhs_cs, mm=ramified_mm_id)
conf = Conformance(state, rhs_id, ramified_mm_id)
print("Conformance RHS_M -> RAM_DSL_MM?", conf.check_nominal(log=True))
def render_ramification():
uml = (""
# Render original and RAMified meta-models
+ plantuml.render_package("DSL Meta-Model", plantuml.render_class_diagram(state, dsl_mm_id))
+ plantuml.render_package("Int Meta-Model", plantuml.render_class_diagram(state, int_mm_id))
+ plantuml.render_package("RAMified DSL Meta-Model", plantuml.render_class_diagram(state, ramified_mm_id))
+ plantuml.render_package("RAMified Int Meta-Model", plantuml.render_class_diagram(state, ramified_int_mm_id))
# Render RAMification traceability links
+ plantuml.render_trace_ramifies(state, dsl_mm_id, ramified_mm_id)
+ plantuml.render_trace_ramifies(state, int_mm_id, ramified_int_mm_id)
)
return uml
def render_lhs_rhs():
uml = render_ramification()
# Render pattern
uml += plantuml.render_package("LHS", plantuml.render_object_diagram(state, lhs_id, ramified_mm_id))
uml += plantuml.render_trace_conformance(state, lhs_id, ramified_mm_id)
# Render pattern
uml += plantuml.render_package("RHS", plantuml.render_object_diagram(state, rhs_id, ramified_mm_id))
uml += plantuml.render_trace_conformance(state, rhs_id, ramified_mm_id)
return uml
def render_all_matches():
uml = render_lhs_rhs()
# Render host graph (before rewriting)
uml += plantuml.render_package("Model (before rewrite)", plantuml.render_object_diagram(state, dsl_m_id, dsl_mm_id))
# Render conformance
uml += plantuml.render_trace_conformance(state, dsl_m_id, dsl_mm_id)
print("matching...")
generator = match_od(state, dsl_m_id, dsl_mm_id, lhs_id, ramified_mm_id)
for match, color in zip(generator, ["red", "orange"]):
print("\nMATCH:\n", match)
# Render every match
uml += plantuml.render_trace_match(state, match, lhs_id, dsl_m_id, color)
print("DONE")
return uml
def render_rewrite():
uml = render_lhs_rhs()
# Render host graph (before rewriting)
uml += plantuml.render_package("Model (before rewrite)", plantuml.render_object_diagram(state, dsl_m_id, dsl_mm_id))
# Render conformance
uml += plantuml.render_trace_conformance(state, dsl_m_id, dsl_mm_id)
generator = match_od(state, dsl_m_id, dsl_mm_id, lhs_id, ramified_mm_id)
for i, (match, color) in enumerate(zip(generator, ["red", "orange"])):
uml += plantuml.render_trace_match(state, match, lhs_id, dsl_m_id, color)
# rewrite happens in-place (which sucks), so we will only modify a clone:
snapshot_dsl_m_id = clone_od(state, dsl_m_id, dsl_mm_id)
rewriter.rewrite(state, lhs_id, rhs_id, ramified_mm_id, match, snapshot_dsl_m_id, dsl_mm_id)
conf = Conformance(state, snapshot_dsl_m_id, dsl_mm_id)
print(f"Conformance DSL_M (after rewrite {i}) -> DSL_MM?", conf.check_nominal(log=True))
# Render host graph (after rewriting)
uml += plantuml.render_package(f"Model (after rewrite {i})", plantuml.render_object_diagram(state, snapshot_dsl_m_id, dsl_mm_id))
# Render match
uml += plantuml.render_trace_match(state, match, rhs_id, snapshot_dsl_m_id, color)
# Render conformance
uml += plantuml.render_trace_conformance(state, snapshot_dsl_m_id, dsl_mm_id)
return uml
# plantuml_str = render_ramification()
# plantuml_str = render_all_matches()
plantuml_str = render_rewrite()
print()
print("==============================================")
print("BEGIN PLANTUML")
print("==============================================")
print(make_plantuml_url(plantuml_str))
print("==============================================")
print("END PLANTUML")
print("==============================================")
if __name__ == "__main__":
main()

View file

@ -1,5 +1,8 @@
p0:PNPlace
p1:PNPlace
p2:PNPlace
p3:PNPlace
p4:PNPlace
t0:PNTransition
:arc (p0 -> t0)
@ -7,4 +10,12 @@ t0:PNTransition
t1:PNTransition
:arc (p1 -> t1)
:arc (t1 -> p0)
:arc (t1 -> p2)
t2:PNTransition
:arc (p2 -> t2)
:arc (t2 -> p0)
t3:PNTransition
:arc (t3 -> p4)

View file

@ -9,3 +9,21 @@ p1s:PNPlaceState {
}
:pn_of (p1s -> p1)
p2s:PNPlaceState {
numTokens = 0;
}
:pn_of (p2s -> p2)
p3s:PNPlaceState {
numTokens = 0;
}
:pn_of (p3s -> p3)
p4s:PNPlaceState {
numTokens = 0;
}
:pn_of (p4s -> p4)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `True`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (p -> t)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `True`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (p -> t)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `True`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (t -> p)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `get_value(this) + 1`;
}
:RAM_pn_of (ps -> p)
# An outgoing arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (t -> p)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `get_value(this) == 0`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (p -> t)

View file

@ -0,0 +1,3 @@
# A place with no tokens:
p:RAM_PNPlace

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `get_value(this) -1`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (p -> t)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `get_value(this) -1`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (p -> t)

View file

@ -0,0 +1 @@
t:RAM_PNTransition

View file

@ -0,0 +1,526 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.5 Chrome/134.0.6998.205 Electron/35.3.0 Safari/537.36" version="27.0.5" pages="2">
<diagram name="main" id="PAlQ5KCi60ZyLzQCaE8o">
<mxGraphModel dx="1042" dy="626" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="start_name" type="Start" ports_exec_out="[&quot;out&quot;]" ports_data_out="[]" id="XJBxcrHkF3XFgZlLdMPd-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="20" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="XJBxcrHkF3XFgZlLdMPd-1" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-2" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-2" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="XJBxcrHkF3XFgZlLdMPd-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="schedule_name" type="Schedule" file="recursion" id="XJBxcrHkF3XFgZlLdMPd-6">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="425" y="260" width="160" height="180" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-7" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="XJBxcrHkF3XFgZlLdMPd-6" vertex="1">
<mxGeometry y="40" width="160" height="140" as="geometry" />
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-8" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-7" vertex="1">
<mxGeometry width="80" height="140" as="geometry">
<mxRectangle width="80" height="140" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="XJBxcrHkF3XFgZlLdMPd-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-8" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="all_places" type="data" id="tqCyT2AFxwHsmUbf2qyE-12">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="XJBxcrHkF3XFgZlLdMPd-8" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-10" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-7" vertex="1">
<mxGeometry x="80" width="80" height="140" as="geometry">
<mxRectangle width="80" height="140" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="XJBxcrHkF3XFgZlLdMPd-11">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-10" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="end_name" type="End" ports_exec_in="[&quot;in&quot;]" ports_data_in="[]" id="XJBxcrHkF3XFgZlLdMPd-13">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="635" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-14" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="XJBxcrHkF3XFgZlLdMPd-13" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-15" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-14" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="XJBxcrHkF3XFgZlLdMPd-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-15" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-17" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-14" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="XJBxcrHkF3XFgZlLdMPd-11" target="XJBxcrHkF3XFgZlLdMPd-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%&#xa;%file%&#xa;matches: %n%" placeholders="1" name="match_name" type="Match" file="rules/places.od" n="4" id="tqCyT2AFxwHsmUbf2qyE-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=60;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="220" y="240" width="160" height="220" as="geometry" />
</mxCell>
</object>
<mxCell id="tqCyT2AFxwHsmUbf2qyE-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="tqCyT2AFxwHsmUbf2qyE-1" vertex="1">
<mxGeometry y="60" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="tqCyT2AFxwHsmUbf2qyE-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="tqCyT2AFxwHsmUbf2qyE-2" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="tqCyT2AFxwHsmUbf2qyE-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="tqCyT2AFxwHsmUbf2qyE-3" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="tqCyT2AFxwHsmUbf2qyE-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="tqCyT2AFxwHsmUbf2qyE-3" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="tqCyT2AFxwHsmUbf2qyE-6" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="tqCyT2AFxwHsmUbf2qyE-2" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="tqCyT2AFxwHsmUbf2qyE-7">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="tqCyT2AFxwHsmUbf2qyE-6" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="success" type="exec" id="tqCyT2AFxwHsmUbf2qyE-8">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="tqCyT2AFxwHsmUbf2qyE-6" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="fail" type="exec" id="tqCyT2AFxwHsmUbf2qyE-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="tqCyT2AFxwHsmUbf2qyE-6" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="tqCyT2AFxwHsmUbf2qyE-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="XJBxcrHkF3XFgZlLdMPd-5" target="tqCyT2AFxwHsmUbf2qyE-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tqCyT2AFxwHsmUbf2qyE-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="tqCyT2AFxwHsmUbf2qyE-8" target="XJBxcrHkF3XFgZlLdMPd-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tqCyT2AFxwHsmUbf2qyE-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="tqCyT2AFxwHsmUbf2qyE-7" target="tqCyT2AFxwHsmUbf2qyE-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="0adWAH9EoXTSZy_ri1wc" name="recursion">
<mxGraphModel dx="1042" dy="626" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="start_name" type="Start" ports_exec_out="[&quot;out&quot;]" ports_data_out="[&quot;all_places&quot;, &quot;comb&quot;]" id="Kt-HEspv_mNIOeUF0m9y-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="10" y="260" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="Kt-HEspv_mNIOeUF0m9y-1" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-2" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-2" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="Kt-HEspv_mNIOeUF0m9y-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="Kt-HEspv_mNIOeUF0m9y-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="all_places" type="data" id="UXJI6ZzX8LQdl2j_TMXK-2">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="Kt-HEspv_mNIOeUF0m9y-4" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="comb" type="data" id="UXJI6ZzX8LQdl2j_TMXK-17">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="Kt-HEspv_mNIOeUF0m9y-4" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="end_name" type="End" ports_exec_in="[&quot;in&quot;]" ports_data_in="[]" id="Kt-HEspv_mNIOeUF0m9y-6">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="540" y="550" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-7" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="Kt-HEspv_mNIOeUF0m9y-6" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-8" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-7" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="Kt-HEspv_mNIOeUF0m9y-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="Kt-HEspv_mNIOeUF0m9y-8" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-10" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-7" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="schedule_name" type="Schedule" file="recursion" id="UQ9mEoFXoNfb_A1GJxno-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="960" y="260" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="UQ9mEoFXoNfb_A1GJxno-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="UQ9mEoFXoNfb_A1GJxno-1" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="UQ9mEoFXoNfb_A1GJxno-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UQ9mEoFXoNfb_A1GJxno-2" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="UQ9mEoFXoNfb_A1GJxno-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UQ9mEoFXoNfb_A1GJxno-3" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="all_places" type="data" id="UXJI6ZzX8LQdl2j_TMXK-3">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UQ9mEoFXoNfb_A1GJxno-3" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="comb" type="data" id="UXJI6ZzX8LQdl2j_TMXK-50">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UQ9mEoFXoNfb_A1GJxno-3" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UQ9mEoFXoNfb_A1GJxno-5" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UQ9mEoFXoNfb_A1GJxno-2" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="UQ9mEoFXoNfb_A1GJxno-6">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UQ9mEoFXoNfb_A1GJxno-5" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="action_name" type="Action" ports_exec_in="[&quot;in&quot;]" ports_exec_out="[&quot;out&quot;, &quot;stop&quot;]" ports_data_in="[&quot;all_places&quot;, &quot;comb&quot;]" ports_data_out="[]" action="if len(data_in[&quot;all_places&quot;]) == len(data_in[&quot;comb&quot;]):&#xa; var[&quot;output_gate&quot;] = &quot;stop&quot;" init="" id="v4SniQMLU1hr-XtfmYLd-9">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="200" y="260" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="v4SniQMLU1hr-XtfmYLd-10" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="v4SniQMLU1hr-XtfmYLd-9" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="v4SniQMLU1hr-XtfmYLd-11" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="v4SniQMLU1hr-XtfmYLd-10" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="v4SniQMLU1hr-XtfmYLd-12">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="v4SniQMLU1hr-XtfmYLd-11" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="all_places" type="data" id="UXJI6ZzX8LQdl2j_TMXK-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="v4SniQMLU1hr-XtfmYLd-11" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="comb" type="data" id="UXJI6ZzX8LQdl2j_TMXK-31">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="v4SniQMLU1hr-XtfmYLd-11" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="v4SniQMLU1hr-XtfmYLd-13" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="v4SniQMLU1hr-XtfmYLd-10" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="v4SniQMLU1hr-XtfmYLd-14">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="v4SniQMLU1hr-XtfmYLd-13" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="stop" type="exec" id="3555_PH_8KkFF3nkISFi-1">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="v4SniQMLU1hr-XtfmYLd-13" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="store_name" type="Store" ports="[&quot;input1&quot;, &quot;input2&quot;]" id="UXJI6ZzX8LQdl2j_TMXK-7">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="710" y="260" width="160" height="380" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-8" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-7" vertex="1">
<mxGeometry y="40" width="160" height="340" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-9" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-8" vertex="1">
<mxGeometry width="80" height="340" as="geometry">
<mxRectangle width="80" height="340" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-10">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-9" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="input1" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-11">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-9" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="input1" type="data" id="UXJI6ZzX8LQdl2j_TMXK-12">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UXJI6ZzX8LQdl2j_TMXK-9" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="input2" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-42">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-9" vertex="1">
<mxGeometry x="10" y="160" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="input2" type="data" id="UXJI6ZzX8LQdl2j_TMXK-43">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UXJI6ZzX8LQdl2j_TMXK-9" vertex="1">
<mxGeometry x="10" y="210" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-13" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-8" vertex="1">
<mxGeometry x="80" width="80" height="340" as="geometry">
<mxRectangle width="80" height="340" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="UXJI6ZzX8LQdl2j_TMXK-14">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UXJI6ZzX8LQdl2j_TMXK-13" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-15">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-13" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="input1" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-13" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="input2" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-44">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-13" vertex="1">
<mxGeometry x="10" y="160" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="UXJI6ZzX8LQdl2j_TMXK-8" source="UXJI6ZzX8LQdl2j_TMXK-44" target="UXJI6ZzX8LQdl2j_TMXK-10" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="190" y="180" />
<mxPoint x="190" y="-60" />
<mxPoint x="-10" y="-60" />
<mxPoint x="-10" y="30" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="vNqiF5lz3jAjMHvjg_tr-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="UXJI6ZzX8LQdl2j_TMXK-8" source="UXJI6ZzX8LQdl2j_TMXK-16" target="UXJI6ZzX8LQdl2j_TMXK-42" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="170" y="80" />
<mxPoint x="170" y="110" />
<mxPoint x="40" y="110" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="loop_name" type="Loop" id="UXJI6ZzX8LQdl2j_TMXK-22">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="430" y="260" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-23" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-22" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-24" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-23" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="UXJI6ZzX8LQdl2j_TMXK-25">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UXJI6ZzX8LQdl2j_TMXK-24" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-26">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-24" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-27" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-23" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="UXJI6ZzX8LQdl2j_TMXK-28">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UXJI6ZzX8LQdl2j_TMXK-27" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="it" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-29">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-27" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-30">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-27" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-17" target="UXJI6ZzX8LQdl2j_TMXK-31" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-2" target="UXJI6ZzX8LQdl2j_TMXK-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="Kt-HEspv_mNIOeUF0m9y-5" target="v4SniQMLU1hr-XtfmYLd-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-2" target="UXJI6ZzX8LQdl2j_TMXK-25" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="190" y="380" />
<mxPoint x="190" y="490" />
<mxPoint x="400" y="490" />
<mxPoint x="400" y="430" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="v4SniQMLU1hr-XtfmYLd-14" target="UXJI6ZzX8LQdl2j_TMXK-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-29" target="UXJI6ZzX8LQdl2j_TMXK-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-17" target="UXJI6ZzX8LQdl2j_TMXK-43" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="180" y="430" />
<mxPoint x="180" y="530" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-48" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-15" target="UQ9mEoFXoNfb_A1GJxno-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-51" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-14" target="UXJI6ZzX8LQdl2j_TMXK-50" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UQ9mEoFXoNfb_A1GJxno-6" target="UXJI6ZzX8LQdl2j_TMXK-26" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1130" y="330" />
<mxPoint x="1130" y="190" />
<mxPoint x="420" y="190" />
<mxPoint x="420" y="330" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-53" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-2" target="UXJI6ZzX8LQdl2j_TMXK-3" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="190" y="380" />
<mxPoint x="190" y="730" />
<mxPoint x="930" y="730" />
<mxPoint x="930" y="380" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="print_name" type="Print" event="False" custom="" id="UXJI6ZzX8LQdl2j_TMXK-54">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="370" y="550" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-55" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-54" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-56" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-55" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-57">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-56" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-58" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UXJI6ZzX8LQdl2j_TMXK-55" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="UXJI6ZzX8LQdl2j_TMXK-59">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UXJI6ZzX8LQdl2j_TMXK-58" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="data" id="UXJI6ZzX8LQdl2j_TMXK-60">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="UXJI6ZzX8LQdl2j_TMXK-58" vertex="1">
<mxGeometry x="-70" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-17" target="UXJI6ZzX8LQdl2j_TMXK-60" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="180" y="430" />
<mxPoint x="180" y="670" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="3555_PH_8KkFF3nkISFi-1" target="UXJI6ZzX8LQdl2j_TMXK-57" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="UXJI6ZzX8LQdl2j_TMXK-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-59" target="Kt-HEspv_mNIOeUF0m9y-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8zcSqG1YZsmCVL_NL7U9-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-30" target="Kt-HEspv_mNIOeUF0m9y-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="vNqiF5lz3jAjMHvjg_tr-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UXJI6ZzX8LQdl2j_TMXK-28" target="UXJI6ZzX8LQdl2j_TMXK-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View file

@ -0,0 +1,66 @@
start:Start
end:End
m:Match{
file = "operational_semantics/transition";
}
nac1:Match{
file = "operational_semantics/all_input_have_token";
n = "1";
}
inputs:Match{
file = "operational_semantics/all_inputs";
}
rinput:Rewrite{
file = "operational_semantics/all_inputs_reduced";
}
outputs:Match{
file = "operational_semantics/all_outputs";
}
routput:Rewrite{
file = "operational_semantics/all_outputs_increased";
}
p:Print{
event = True;
}
p2:Print{
event = False;
custom = `"succesfully execuded a petrinet transition"`;
}
l:Loop
l2:Loop
l3:Loop
:Conn_exec (start -> m) {from="out"; to="in";}
:Conn_exec (m -> l) {from="success"; to="in";}
:Conn_exec (l -> nac1) {from="it"; to="in";}
:Conn_exec (l -> end) {from="out"; to="in";}
:Conn_exec (nac1 -> l) {from="success"; to="in";}
:Conn_exec (nac1 -> inputs) {from="fail"; to="in";}
:Conn_exec (inputs -> l2) {from="success"; to="in";}
:Conn_exec (inputs -> l2) {from="fail"; to="in";}
:Conn_exec (l2 -> rinput) {from="it"; to="in";}
:Conn_exec (rinput -> l2) {from="out"; to="in";}
:Conn_exec (l2 -> outputs) {from="out"; to="in";}
:Conn_exec (outputs -> l3) {from="success"; to="in";}
:Conn_exec (outputs -> l3) {from="fail"; to="in";}
:Conn_exec (l3 -> routput) {from="it"; to="in";}
:Conn_exec (routput -> l3) {from="out"; to="in";}
:Conn_exec (l3 -> p2) {from="out"; to="in";}
:Conn_exec (p2 -> end) {from="out"; to="in";}
:Conn_data (m -> l) {from="out"; to="in";}
:Conn_data (l -> nac1) {from="out"; to="in";}
:Conn_data (l -> inputs) {from="out"; to="in";}
:Conn_data (inputs -> l2) {from="out"; to="in";}
:Conn_data (l2 -> rinput) {from="out"; to="in";}
:Conn_data (l -> outputs) {from="out"; to="in";}
:Conn_data (outputs -> l3) {from="out"; to="in";}
:Conn_data (l3 -> routput) {from="out"; to="in";}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,915 @@
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.1.1 Chrome/134.0.6998.205 Electron/35.5.0 Safari/537.36" version="26.1.1" pages="4">
<diagram name="main" id="7loCSpFFTrw_GtNaECtm">
<mxGraphModel dx="912" dy="719" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="start" type="Start" id="okR2fhRwQtHO20KEb0BA-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="100" y="240" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="okR2fhRwQtHO20KEb0BA-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="okR2fhRwQtHO20KEb0BA-1" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="okR2fhRwQtHO20KEb0BA-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="okR2fhRwQtHO20KEb0BA-2" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="okR2fhRwQtHO20KEb0BA-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="okR2fhRwQtHO20KEb0BA-2" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="okR2fhRwQtHO20KEb0BA-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="okR2fhRwQtHO20KEb0BA-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%&#xa;%file%&#xa;matches: %n%" placeholders="1" name="all transtions" type="Match" file="rules/transition.od" n="" id="okR2fhRwQtHO20KEb0BA-11">
<mxCell style="shape=table;childLayout=tableLayout;startSize=60;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="300" y="220" width="160" height="220" as="geometry" />
</mxCell>
</object>
<mxCell id="okR2fhRwQtHO20KEb0BA-12" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="okR2fhRwQtHO20KEb0BA-11" vertex="1">
<mxGeometry y="60" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="okR2fhRwQtHO20KEb0BA-13" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="okR2fhRwQtHO20KEb0BA-12" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="okR2fhRwQtHO20KEb0BA-14">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="okR2fhRwQtHO20KEb0BA-13" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="okR2fhRwQtHO20KEb0BA-15">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="okR2fhRwQtHO20KEb0BA-13" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="okR2fhRwQtHO20KEb0BA-16" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="okR2fhRwQtHO20KEb0BA-12" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="okR2fhRwQtHO20KEb0BA-17">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="okR2fhRwQtHO20KEb0BA-16" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="success" type="exec" id="okR2fhRwQtHO20KEb0BA-18">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="okR2fhRwQtHO20KEb0BA-16" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="fail" type="exec" id="okR2fhRwQtHO20KEb0BA-19">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="okR2fhRwQtHO20KEb0BA-16" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="okR2fhRwQtHO20KEb0BA-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" parent="1" source="okR2fhRwQtHO20KEb0BA-5" target="okR2fhRwQtHO20KEb0BA-15" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="find first that can fire" type="Schedule" file="check_nac" id="AWz2q_jGxnOfZjJ20oEo-31">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="520" y="240" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="AWz2q_jGxnOfZjJ20oEo-32" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="AWz2q_jGxnOfZjJ20oEo-31" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="AWz2q_jGxnOfZjJ20oEo-33" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="AWz2q_jGxnOfZjJ20oEo-32" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="AWz2q_jGxnOfZjJ20oEo-34">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="AWz2q_jGxnOfZjJ20oEo-33" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="_ZUP5PYB2ZkPahpFH5fo-1">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="AWz2q_jGxnOfZjJ20oEo-33" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="AWz2q_jGxnOfZjJ20oEo-35" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="AWz2q_jGxnOfZjJ20oEo-32" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="AWz2q_jGxnOfZjJ20oEo-36">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="AWz2q_jGxnOfZjJ20oEo-35" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="_ZUP5PYB2ZkPahpFH5fo-3">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="AWz2q_jGxnOfZjJ20oEo-35" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="_ZUP5PYB2ZkPahpFH5fo-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="okR2fhRwQtHO20KEb0BA-17" target="_ZUP5PYB2ZkPahpFH5fo-1" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="500" y="410" />
<mxPoint x="500" y="360" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="reduce incoming" type="Schedule" file="reduce_incoming" id="7FO2QKo1IHTQBZ6BJbAA-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="759.9300000000001" y="130" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="7FO2QKo1IHTQBZ6BJbAA-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="7FO2QKo1IHTQBZ6BJbAA-1" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="7FO2QKo1IHTQBZ6BJbAA-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="7FO2QKo1IHTQBZ6BJbAA-2" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="7FO2QKo1IHTQBZ6BJbAA-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="7FO2QKo1IHTQBZ6BJbAA-3" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="7FO2QKo1IHTQBZ6BJbAA-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="7FO2QKo1IHTQBZ6BJbAA-3" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="7FO2QKo1IHTQBZ6BJbAA-6" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="7FO2QKo1IHTQBZ6BJbAA-2" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="7FO2QKo1IHTQBZ6BJbAA-7">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="7FO2QKo1IHTQBZ6BJbAA-6" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="increase outgoing&#xa;" type="Schedule" file="increase_outgoing" id="7FO2QKo1IHTQBZ6BJbAA-10">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="759.9300000000001" y="360" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="7FO2QKo1IHTQBZ6BJbAA-11" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="7FO2QKo1IHTQBZ6BJbAA-10" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="7FO2QKo1IHTQBZ6BJbAA-12" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="7FO2QKo1IHTQBZ6BJbAA-11" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="7FO2QKo1IHTQBZ6BJbAA-13">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="7FO2QKo1IHTQBZ6BJbAA-12" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="7FO2QKo1IHTQBZ6BJbAA-14">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="7FO2QKo1IHTQBZ6BJbAA-12" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="7FO2QKo1IHTQBZ6BJbAA-15" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="7FO2QKo1IHTQBZ6BJbAA-11" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="7FO2QKo1IHTQBZ6BJbAA-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="7FO2QKo1IHTQBZ6BJbAA-15" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="qfxbZ8cPFIYkKl1hvR_z-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" parent="1" source="7FO2QKo1IHTQBZ6BJbAA-7" target="7FO2QKo1IHTQBZ6BJbAA-13" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="939.9300000000001" y="200" />
<mxPoint x="939.9300000000001" y="315" />
<mxPoint x="739.9300000000001" y="315" />
<mxPoint x="739.9300000000001" y="430" />
</Array>
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="end" type="End" ports_exec_in="[&quot;in&quot;]" ports_data_in="[]" id="qfxbZ8cPFIYkKl1hvR_z-8">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="759.9300000000001" y="550" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="qfxbZ8cPFIYkKl1hvR_z-9" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="qfxbZ8cPFIYkKl1hvR_z-8" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="qfxbZ8cPFIYkKl1hvR_z-10" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="qfxbZ8cPFIYkKl1hvR_z-9" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="qfxbZ8cPFIYkKl1hvR_z-11">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="qfxbZ8cPFIYkKl1hvR_z-10" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="qfxbZ8cPFIYkKl1hvR_z-12" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="qfxbZ8cPFIYkKl1hvR_z-9" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="16WNXanlPmjoLkNVfXpS-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" parent="1" source="okR2fhRwQtHO20KEb0BA-18" target="AWz2q_jGxnOfZjJ20oEo-34" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="16WNXanlPmjoLkNVfXpS-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" parent="1" source="7FO2QKo1IHTQBZ6BJbAA-16" target="qfxbZ8cPFIYkKl1hvR_z-11" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="939.9300000000001" y="430" />
<mxPoint x="939.9300000000001" y="530" />
<mxPoint x="739.9300000000001" y="530" />
<mxPoint x="739.9300000000001" y="620" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="16WNXanlPmjoLkNVfXpS-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;jumpStyle=gap;jumpSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" parent="1" source="okR2fhRwQtHO20KEb0BA-19" target="qfxbZ8cPFIYkKl1hvR_z-11" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="480" y="360" />
<mxPoint x="480" y="620" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="HUEgSa0tznzWzqEGNiE2-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="_ZUP5PYB2ZkPahpFH5fo-3" target="7FO2QKo1IHTQBZ6BJbAA-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="HUEgSa0tznzWzqEGNiE2-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="_ZUP5PYB2ZkPahpFH5fo-3" target="7FO2QKo1IHTQBZ6BJbAA-14" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="HUEgSa0tznzWzqEGNiE2-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" parent="1" source="AWz2q_jGxnOfZjJ20oEo-36" target="7FO2QKo1IHTQBZ6BJbAA-4" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="700" y="310" />
<mxPoint x="700" y="200" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="tn9M2oGm5-WwrC7q8hvp" name="check_nac">
<mxGraphModel dx="1158" dy="696" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="sub_start" type="Start" ports_data_out="[&quot;t&quot;, &quot;foo&quot;]" ports_exec_out="[&quot;out&quot;, &quot;foo&quot;]" id="45lnt7s__IUFePRUFwyU-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="40" y="240" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="45lnt7s__IUFePRUFwyU-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="45lnt7s__IUFePRUFwyU-1" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="45lnt7s__IUFePRUFwyU-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="45lnt7s__IUFePRUFwyU-2" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="45lnt7s__IUFePRUFwyU-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="45lnt7s__IUFePRUFwyU-2" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="45lnt7s__IUFePRUFwyU-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="45lnt7s__IUFePRUFwyU-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="45lnt7s__IUFePRUFwyU-39">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="45lnt7s__IUFePRUFwyU-4" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="sub_end" type="End" ports_data_in="[&quot;t&quot;]" ports_exec_in="[&quot;rrrreee&quot;, &quot;in&quot;]" id="45lnt7s__IUFePRUFwyU-6">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="640" y="290" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="45lnt7s__IUFePRUFwyU-7" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="45lnt7s__IUFePRUFwyU-6" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="45lnt7s__IUFePRUFwyU-8" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="45lnt7s__IUFePRUFwyU-7" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="45lnt7s__IUFePRUFwyU-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="45lnt7s__IUFePRUFwyU-8" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="2n85NC4Wvb6VNMCIjbAe-2">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="45lnt7s__IUFePRUFwyU-8" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="45lnt7s__IUFePRUFwyU-10" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="45lnt7s__IUFePRUFwyU-7" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="iterate transitions" type="Loop" id="L95llld_XDiE7aqnH3Eh-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="240" y="240" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="L95llld_XDiE7aqnH3Eh-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="L95llld_XDiE7aqnH3Eh-1" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="L95llld_XDiE7aqnH3Eh-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="L95llld_XDiE7aqnH3Eh-2" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="L95llld_XDiE7aqnH3Eh-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="L95llld_XDiE7aqnH3Eh-3" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="L95llld_XDiE7aqnH3Eh-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="L95llld_XDiE7aqnH3Eh-3" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="L95llld_XDiE7aqnH3Eh-6" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="L95llld_XDiE7aqnH3Eh-2" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="L95llld_XDiE7aqnH3Eh-7">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="L95llld_XDiE7aqnH3Eh-6" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="it" type="exec" id="L95llld_XDiE7aqnH3Eh-8">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="L95llld_XDiE7aqnH3Eh-6" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="exec" id="L95llld_XDiE7aqnH3Eh-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="L95llld_XDiE7aqnH3Eh-6" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="L95llld_XDiE7aqnH3Eh-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="45lnt7s__IUFePRUFwyU-5" target="L95llld_XDiE7aqnH3Eh-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="L95llld_XDiE7aqnH3Eh-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="45lnt7s__IUFePRUFwyU-39" target="L95llld_XDiE7aqnH3Eh-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%&#xa;%file%&#xa;matches: %n%" placeholders="1" name="check nac" type="Match" file="rules/input_without_token.od" n="1" id="L95llld_XDiE7aqnH3Eh-12">
<mxCell style="shape=table;childLayout=tableLayout;startSize=60;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="440" y="220" width="160" height="220" as="geometry" />
</mxCell>
</object>
<mxCell id="L95llld_XDiE7aqnH3Eh-13" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="L95llld_XDiE7aqnH3Eh-12" vertex="1">
<mxGeometry y="60" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="L95llld_XDiE7aqnH3Eh-14" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="L95llld_XDiE7aqnH3Eh-13" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="L95llld_XDiE7aqnH3Eh-15">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="L95llld_XDiE7aqnH3Eh-14" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="L95llld_XDiE7aqnH3Eh-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="L95llld_XDiE7aqnH3Eh-14" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="L95llld_XDiE7aqnH3Eh-17" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="L95llld_XDiE7aqnH3Eh-13" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="L95llld_XDiE7aqnH3Eh-18">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="L95llld_XDiE7aqnH3Eh-17" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="success" type="exec" id="L95llld_XDiE7aqnH3Eh-19">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="L95llld_XDiE7aqnH3Eh-17" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="fail" type="exec" id="L95llld_XDiE7aqnH3Eh-20">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="L95llld_XDiE7aqnH3Eh-17" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="L95llld_XDiE7aqnH3Eh-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="L95llld_XDiE7aqnH3Eh-8" target="L95llld_XDiE7aqnH3Eh-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="L95llld_XDiE7aqnH3Eh-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="L95llld_XDiE7aqnH3Eh-7" target="L95llld_XDiE7aqnH3Eh-15" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="iKvoEYQEFeyBr_GkI9vg-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="L95llld_XDiE7aqnH3Eh-19" target="L95llld_XDiE7aqnH3Eh-5" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="630" y="200" as="targetPoint" />
<Array as="points">
<mxPoint x="620" y="310" />
<mxPoint x="620" y="200" />
<mxPoint x="220" y="200" />
<mxPoint x="220" y="300" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="dMiStd5tzY-ImjgYRODK-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="L95llld_XDiE7aqnH3Eh-20" target="45lnt7s__IUFePRUFwyU-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dMiStd5tzY-ImjgYRODK-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="L95llld_XDiE7aqnH3Eh-7" target="2n85NC4Wvb6VNMCIjbAe-2">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="420" y="410" />
<mxPoint x="420" y="470" />
<mxPoint x="620" y="470" />
<mxPoint x="620" y="410" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="EAsDi4mdSkZfbsRIt0-E" name="reduce_incoming">
<mxGraphModel dx="1892" dy="626" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="sub_start" type="Start" ports_data_out="[&quot;t&quot;, &quot;foo&quot;]" ports_exec_out="[&quot;out&quot;, &quot;foo&quot;]" id="BUnm0WgavkPBicxchqk0-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="-200" y="240" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="BUnm0WgavkPBicxchqk0-1" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-2" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-2" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="BUnm0WgavkPBicxchqk0-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="BUnm0WgavkPBicxchqk0-6">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="BUnm0WgavkPBicxchqk0-4" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="sub_end" type="End" ports_data_in="[]" ports_exec_in="[&quot;rrrreee&quot;, &quot;in&quot;]" id="BUnm0WgavkPBicxchqk0-7">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="640" y="240" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-8" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="BUnm0WgavkPBicxchqk0-7" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-9" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-8" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="BUnm0WgavkPBicxchqk0-10">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-9" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-12" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-8" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="iterate places" type="Loop" id="BUnm0WgavkPBicxchqk0-13">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="200" y="240" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-14" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="BUnm0WgavkPBicxchqk0-13" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-15" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-14" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="BUnm0WgavkPBicxchqk0-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="BUnm0WgavkPBicxchqk0-15" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="BUnm0WgavkPBicxchqk0-17">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-15" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-18" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-14" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="BUnm0WgavkPBicxchqk0-19">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="BUnm0WgavkPBicxchqk0-18" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="it" type="exec" id="BUnm0WgavkPBicxchqk0-20">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-18" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="exec" id="BUnm0WgavkPBicxchqk0-21">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-18" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%&#xa;%file%&#xa;matches: %n%" placeholders="1" name="incoming places" type="Match" file="rules/all_incoming.od" n="1" id="BUnm0WgavkPBicxchqk0-52">
<mxCell style="shape=table;childLayout=tableLayout;startSize=60;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry y="220" width="160" height="220" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-53" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="BUnm0WgavkPBicxchqk0-52" vertex="1">
<mxGeometry y="60" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-54" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-53" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="BUnm0WgavkPBicxchqk0-55">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="BUnm0WgavkPBicxchqk0-54" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="BUnm0WgavkPBicxchqk0-56">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-54" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-57" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-53" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="BUnm0WgavkPBicxchqk0-58">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="BUnm0WgavkPBicxchqk0-57" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="success" type="exec" id="BUnm0WgavkPBicxchqk0-59">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-57" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="fail" type="exec" id="BUnm0WgavkPBicxchqk0-60">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-57" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-5" target="BUnm0WgavkPBicxchqk0-56" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-6" target="BUnm0WgavkPBicxchqk0-55" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-60" target="BUnm0WgavkPBicxchqk0-17" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="180" y="360" />
<mxPoint x="180" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-59" target="BUnm0WgavkPBicxchqk0-17" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-58" target="BUnm0WgavkPBicxchqk0-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="reduce place" type="Rewrite" file="rules/reduce_incoming.od" id="BUnm0WgavkPBicxchqk0-66">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="420" y="240.0000000000001" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-67" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="BUnm0WgavkPBicxchqk0-66" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="BUnm0WgavkPBicxchqk0-68" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-67" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="BUnm0WgavkPBicxchqk0-69">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-68" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-70" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="BUnm0WgavkPBicxchqk0-67" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="BUnm0WgavkPBicxchqk0-71">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="BUnm0WgavkPBicxchqk0-70" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="data" id="BUnm0WgavkPBicxchqk0-72">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="BUnm0WgavkPBicxchqk0-70" vertex="1">
<mxGeometry x="-70" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="data" id="BUnm0WgavkPBicxchqk0-73">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="BUnm0WgavkPBicxchqk0-70" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="BUnm0WgavkPBicxchqk0-74" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-19" target="BUnm0WgavkPBicxchqk0-72" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="400" y="410" />
<mxPoint x="400" y="360" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="sY74cFRy-IzXkK1T1M-7-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="BUnm0WgavkPBicxchqk0-21" target="BUnm0WgavkPBicxchqk0-10" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="380" y="360" />
<mxPoint x="380" y="430" />
<mxPoint x="620" y="430" />
<mxPoint x="620" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="sY74cFRy-IzXkK1T1M-7-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-20" target="BUnm0WgavkPBicxchqk0-69" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="sY74cFRy-IzXkK1T1M-7-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BUnm0WgavkPBicxchqk0-71" target="BUnm0WgavkPBicxchqk0-17" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="600" y="310" />
<mxPoint x="600" y="220" />
<mxPoint x="180" y="220" />
<mxPoint x="180" y="310" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="_IoT90r4-d_BBqiD0-W3" name="increase_outgoing">
<mxGraphModel dx="1892" dy="626" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="sub_start" type="Start" ports_data_out="[&quot;t&quot;, &quot;foo&quot;]" ports_exec_out="[&quot;out&quot;, &quot;foo&quot;]" id="xKz7S_Fbuw8o9D4hMjwY-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="-200" y="240" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-1" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-2" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-2" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="t" type="data" id="xKz7S_Fbuw8o9D4hMjwY-6">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="xKz7S_Fbuw8o9D4hMjwY-4" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="sub_end" type="End" ports_data_in="[]" ports_exec_in="[&quot;rrrreee&quot;, &quot;in&quot;]" id="xKz7S_Fbuw8o9D4hMjwY-7">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="640" y="240" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-8" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-7" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-9" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-8" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-10">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-9" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-11" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-8" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="%name%: %type%" placeholders="1" name="iterate places" type="Loop" id="xKz7S_Fbuw8o9D4hMjwY-12">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="200" y="240" width="160" height="200" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-13" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-12" vertex="1">
<mxGeometry y="40" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-14" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-13" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="xKz7S_Fbuw8o9D4hMjwY-15">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="xKz7S_Fbuw8o9D4hMjwY-14" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-14" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-17" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-13" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="xKz7S_Fbuw8o9D4hMjwY-18">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="xKz7S_Fbuw8o9D4hMjwY-17" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="it" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-19">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-17" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-20">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-17" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-19" target="xKz7S_Fbuw8o9D4hMjwY-40" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="450" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<object label="%name%: %type%&#xa;%file%&#xa;matches: %n%" placeholders="1" name="outgoing places" type="Match" file="rules/all_outgoing.od" n="1" id="xKz7S_Fbuw8o9D4hMjwY-23">
<mxCell style="shape=table;childLayout=tableLayout;startSize=60;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry y="220" width="160" height="220" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-24" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-23" vertex="1">
<mxGeometry y="60" width="160" height="160" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-25" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-24" vertex="1">
<mxGeometry width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="data" id="xKz7S_Fbuw8o9D4hMjwY-26">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="xKz7S_Fbuw8o9D4hMjwY-25" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-27">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-25" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-28" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-24" vertex="1">
<mxGeometry x="80" width="80" height="160" as="geometry">
<mxRectangle width="80" height="160" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="data" id="xKz7S_Fbuw8o9D4hMjwY-29">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="xKz7S_Fbuw8o9D4hMjwY-28" vertex="1">
<mxGeometry x="10" y="110" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="success" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-30">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-28" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="fail" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-31">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-28" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-5" target="xKz7S_Fbuw8o9D4hMjwY-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-6" target="xKz7S_Fbuw8o9D4hMjwY-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-31" target="xKz7S_Fbuw8o9D4hMjwY-16" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="180" y="360" />
<mxPoint x="180" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-30" target="xKz7S_Fbuw8o9D4hMjwY-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-29" target="xKz7S_Fbuw8o9D4hMjwY-15" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="increase place" type="Rewrite" file="rules/increase_outgoing.od" id="xKz7S_Fbuw8o9D4hMjwY-37">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="420" y="240.0000000000001" width="160" height="150" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-38" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-37" vertex="1">
<mxGeometry y="40" width="160" height="110" as="geometry" />
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-39" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-38" vertex="1">
<mxGeometry width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-40">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-39" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-41" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="xKz7S_Fbuw8o9D4hMjwY-38" vertex="1">
<mxGeometry x="80" width="80" height="110" as="geometry">
<mxRectangle width="80" height="110" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="xKz7S_Fbuw8o9D4hMjwY-42">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="xKz7S_Fbuw8o9D4hMjwY-41" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="in" type="data" id="xKz7S_Fbuw8o9D4hMjwY-43">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="xKz7S_Fbuw8o9D4hMjwY-41" vertex="1">
<mxGeometry x="-70" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="out" type="data" id="xKz7S_Fbuw8o9D4hMjwY-44">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="xKz7S_Fbuw8o9D4hMjwY-41" vertex="1">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-18" target="xKz7S_Fbuw8o9D4hMjwY-43" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="400" y="410" />
<mxPoint x="400" y="360" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="xKz7S_Fbuw8o9D4hMjwY-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;jumpStyle=gap;jumpSize=10;" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-20" target="xKz7S_Fbuw8o9D4hMjwY-10" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="380" y="360" />
<mxPoint x="380" y="430" />
<mxPoint x="620" y="430" />
<mxPoint x="620" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="f9_bY4aOCWeb4ynzbNl7-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xKz7S_Fbuw8o9D4hMjwY-42" target="xKz7S_Fbuw8o9D4hMjwY-16">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="600" y="310" />
<mxPoint x="600" y="220" />
<mxPoint x="180" y="220" />
<mxPoint x="180" y="310" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View file

@ -0,0 +1,217 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.5 Chrome/134.0.6998.205 Electron/35.3.0 Safari/537.36" version="27.0.5" pages="2">
<diagram name="main" id="PAlQ5KCi60ZyLzQCaE8o">
<mxGraphModel dx="1042" dy="626" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="start_name" type="Start" ports_exec_out="[&quot;out&quot;]" ports_data_out="[]" id="XJBxcrHkF3XFgZlLdMPd-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="90" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="XJBxcrHkF3XFgZlLdMPd-1" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-2" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-2" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="XJBxcrHkF3XFgZlLdMPd-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="schedule_name" type="Schedule" file="recursion" id="XJBxcrHkF3XFgZlLdMPd-6">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="340" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-7" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="XJBxcrHkF3XFgZlLdMPd-6" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-8" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-7" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="XJBxcrHkF3XFgZlLdMPd-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-8" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-10" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-7" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="XJBxcrHkF3XFgZlLdMPd-11">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-10" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="XJBxcrHkF3XFgZlLdMPd-5" target="XJBxcrHkF3XFgZlLdMPd-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%" placeholders="1" name="end_name" type="End" ports_exec_in="[&quot;in&quot;]" ports_data_in="[]" id="XJBxcrHkF3XFgZlLdMPd-13">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="550" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-14" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="XJBxcrHkF3XFgZlLdMPd-13" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-15" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-14" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="XJBxcrHkF3XFgZlLdMPd-16">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="XJBxcrHkF3XFgZlLdMPd-15" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-17" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="XJBxcrHkF3XFgZlLdMPd-14" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XJBxcrHkF3XFgZlLdMPd-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="XJBxcrHkF3XFgZlLdMPd-11" target="XJBxcrHkF3XFgZlLdMPd-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="0adWAH9EoXTSZy_ri1wc" name="recursion">
<mxGraphModel dx="1042" dy="626" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="%name%: %type%" placeholders="1" name="start_name" type="Start" ports_exec_out="[&quot;out&quot;]" ports_data_out="[]" id="Kt-HEspv_mNIOeUF0m9y-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="50" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="Kt-HEspv_mNIOeUF0m9y-1" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-2" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-4" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-2" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="Kt-HEspv_mNIOeUF0m9y-5">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="Kt-HEspv_mNIOeUF0m9y-4" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="%name%: %type%" placeholders="1" name="end_name" type="End" ports_exec_in="[&quot;in&quot;]" ports_data_in="[]" id="Kt-HEspv_mNIOeUF0m9y-6">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="625" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-7" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="Kt-HEspv_mNIOeUF0m9y-6" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-8" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-7" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="Kt-HEspv_mNIOeUF0m9y-9">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="Kt-HEspv_mNIOeUF0m9y-8" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="Kt-HEspv_mNIOeUF0m9y-10" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="Kt-HEspv_mNIOeUF0m9y-7" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="%name%: %type%&#xa;%file%" placeholders="1" name="schedule_name" type="Schedule" file="recursion" id="UQ9mEoFXoNfb_A1GJxno-1">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" parent="1" vertex="1">
<mxGeometry x="425" y="260" width="160" height="100" as="geometry" />
</mxCell>
</object>
<mxCell id="UQ9mEoFXoNfb_A1GJxno-2" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" parent="UQ9mEoFXoNfb_A1GJxno-1" vertex="1">
<mxGeometry y="40" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="UQ9mEoFXoNfb_A1GJxno-3" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UQ9mEoFXoNfb_A1GJxno-2" vertex="1">
<mxGeometry width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="UQ9mEoFXoNfb_A1GJxno-4">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UQ9mEoFXoNfb_A1GJxno-3" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UQ9mEoFXoNfb_A1GJxno-5" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" parent="UQ9mEoFXoNfb_A1GJxno-2" vertex="1">
<mxGeometry x="80" width="80" height="60" as="geometry">
<mxRectangle width="80" height="60" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="UQ9mEoFXoNfb_A1GJxno-6">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="UQ9mEoFXoNfb_A1GJxno-5" vertex="1">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="UQ9mEoFXoNfb_A1GJxno-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="UQ9mEoFXoNfb_A1GJxno-6" target="Kt-HEspv_mNIOeUF0m9y-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<object label="%name%: %type%" placeholders="1" name="action_name" type="Action" ports_exec_in="[&quot;in&quot;]" ports_exec_out="[&quot;out&quot;, &quot;stop&quot;]" ports_data_in="[]" ports_data_out="[]" action="print(f&quot;hello world {globals[&quot;n&quot;]}&quot;)&#xa;globals[&quot;n&quot;] += 1&#xa;if globals[&quot;n&quot;] &gt; 50:&#xa; var[&quot;output_gate&quot;] = &quot;stop&quot;" init="globals[&quot;n&quot;] = 0" id="v4SniQMLU1hr-XtfmYLd-9">
<mxCell style="shape=table;childLayout=tableLayout;startSize=40;collapsible=0;recursiveResize=1;expand=0;fontStyle=1;editable=1;movable=1;resizable=1;rotatable=0;deletable=1;locked=0;connectable=0;allowArrows=0;pointerEvents=0;perimeter=rectanglePerimeter;rounded=1;container=1;dropTarget=0;swimlaneHead=1;swimlaneBody=1;top=1;noLabel=0;autosize=0;resizeHeight=0;spacing=2;metaEdit=1;resizeWidth=0;arcSize=10;" vertex="1" parent="1">
<mxGeometry x="230" y="120" width="160" height="170" as="geometry" />
</mxCell>
</object>
<mxCell id="v4SniQMLU1hr-XtfmYLd-10" value="" style="shape=tableRow;horizontal=0;swimlaneHead=0;swimlaneBody=0;top=0;left=0;strokeColor=inherit;bottom=0;right=0;dropTarget=0;fontStyle=0;fillColor=none;points=[[0,0.5],[1,0.5]];startSize=0;collapsible=0;recursiveResize=1;expand=0;rounded=0;allowArrows=0;connectable=0;autosize=1;resizeHeight=1;rotatable=0;" vertex="1" parent="v4SniQMLU1hr-XtfmYLd-9">
<mxGeometry y="40" width="160" height="130" as="geometry" />
</mxCell>
<mxCell id="v4SniQMLU1hr-XtfmYLd-11" value="Input" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=60;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" vertex="1" parent="v4SniQMLU1hr-XtfmYLd-10">
<mxGeometry width="80" height="130" as="geometry">
<mxRectangle width="80" height="130" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="in" type="exec" id="v4SniQMLU1hr-XtfmYLd-12">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="v4SniQMLU1hr-XtfmYLd-11">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="v4SniQMLU1hr-XtfmYLd-13" value="Output" style="swimlane;swimlaneHead=0;swimlaneBody=0;fontStyle=0;strokeColor=inherit;connectable=0;fillColor=none;startSize=40;collapsible=0;recursiveResize=1;expand=0;allowArrows=0;autosize=1;rotatable=0;noLabel=1;overflow=hidden;swimlaneLine=0;editable=0;" vertex="1" parent="v4SniQMLU1hr-XtfmYLd-10">
<mxGeometry x="80" width="80" height="130" as="geometry">
<mxRectangle width="80" height="130" as="alternateBounds" />
</mxGeometry>
</mxCell>
<object label="out" type="exec" id="v4SniQMLU1hr-XtfmYLd-14">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="v4SniQMLU1hr-XtfmYLd-13">
<mxGeometry x="10" y="10" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="stop" type="exec" id="3555_PH_8KkFF3nkISFi-1">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="v4SniQMLU1hr-XtfmYLd-13">
<mxGeometry x="10" y="60" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="v4SniQMLU1hr-XtfmYLd-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Kt-HEspv_mNIOeUF0m9y-5" target="v4SniQMLU1hr-XtfmYLd-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="v4SniQMLU1hr-XtfmYLd-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="v4SniQMLU1hr-XtfmYLd-14" target="UQ9mEoFXoNfb_A1GJxno-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3555_PH_8KkFF3nkISFi-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="3555_PH_8KkFF3nkISFi-1" target="Kt-HEspv_mNIOeUF0m9y-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View file

@ -0,0 +1,4 @@
start: Start
end: End
:Conn_exec (start -> end) {from="tfuy"; to="in";}

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `True`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (p -> t)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `get_value(this) -1`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (t -> p)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `True`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (t -> p)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `set_value(this, get_value(this) + 1)`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (t -> p)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `True`;
}
:RAM_pn_of (ps -> p)
# An outgoing arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (t -> p)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `get_value(this) + 1`;
}
:RAM_pn_of (ps -> p)
# An outgoing arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (t -> p)

View file

@ -0,0 +1,13 @@
# A place with no tokens:
p:RAM_PNPlace
ps:RAM_PNPlaceState {
RAM_numTokens = `get_value(this) == 0`;
}
:RAM_pn_of (ps -> p)
# An incoming arc from that place to our transition:
t:RAM_PNTransition
:RAM_arc (p -> t)

View file

@ -1 +1 @@
t:RAM_PNTransition
t:RAM_PNTransition

View file

@ -0,0 +1 @@
t:RAM_PNTransition

View file

@ -0,0 +1,12 @@
digraph G {
rankdir=LR;
center=true;
margin=1;
nodesep=1;
subgraph places {
node [fontname=Arial,fontsize=10,shape=circle,fixedsize=true,label="", height=.35,width=.35];
{% for place in places %}
{{ place[0] }} [label="{{ place[1] }}_{{ place[2] }}"]
{% endfor %}
}
}

View file

@ -1,3 +1,7 @@
import os
from jinja2 import Environment, FileSystemLoader
from api.od import ODAPI
from concrete_syntax.graphviz.make_url import show_graphviz
from concrete_syntax.graphviz.renderer import make_graphviz_id
@ -16,13 +20,24 @@ def render_tokens(num_tokens: int):
return str(num_tokens)
def render_petri_net_to_dot(od: ODAPI) -> str:
env = Environment(
loader=FileSystemLoader(
os.path.dirname(__file__)
)
)
env.trim_blocks = True
env.lstrip_blocks = True
template_dot = env.get_template("petrinet_renderer.j2")
with open("test_pet.dot", "w", encoding="utf-8") as f_dot:
places = [(make_graphviz_id(place), place_name, render_tokens(od.get_slot_value(od.get_source(od.get_incoming(place, "pn_of")[0]), "numTokens"))) for place_name, place in od.get_all_instances("PNPlace")]
f_dot.write(template_dot.render({"places": places}))
dot = ""
dot += "rankdir=LR;"
dot += "center=true;"
dot += "margin=1;"
dot += "nodesep=1;"
dot += "subgraph places {"
dot += " node [fontname=Arial,fontsize=10,shape=circle,fixedsize=true,label=\"\", height=.35,width=.35];"
dot += "rankdir=LR;\n"
dot += "center=true;\n"
dot += "margin=1;\n"
dot += "nodesep=1;\n"
dot += "subgraph places {\n"
dot += " node [fontname=Arial,fontsize=10,shape=circle,fixedsize=true,label=\"\", height=.35,width=.35];\n"
for place_name, place in od.get_all_instances("PNPlace"):
# place_name = od.get_name(place)
try:

View file

@ -1,14 +1,12 @@
from state.devstate import DevState
from api.od import ODAPI
from icecream import ic
from concrete_syntax.textual_od.renderer import render_od
# from concrete_syntax.textual_od.renderer_jinja2 import render_od_jinja2
from bootstrap.scd import bootstrap_scd
from transformation.schedule.Tests import Test_xmlparser
from util import loader
from transformation.rule import RuleMatcherRewriter, ActionGenerator
from transformation.ramify import ramify
from examples.semantics.operational import simulator
from examples.petrinet.renderer import show_petri_net
from transformation.schedule.rule_scheduler import *
if __name__ == "__main__":
import os
@ -30,35 +28,26 @@ if __name__ == "__main__":
# m_rt_initial_cs = m_cs + read_file('models/m_example_simple_rt_initial.od')
# m_cs = read_file('models/m_example_mutex.od')
# m_rt_initial_cs = m_cs + read_file('models/m_example_mutex_rt_initial.od')
m_cs = read_file('models/m_example_inharc.od')
m_rt_initial_cs = m_cs + read_file('models/m_example_inharc_rt_initial.od')
m_cs = read_file('models/m_example_simple.od')
m_rt_initial_cs = m_cs + read_file('models/m_example_simple_rt_initial.od')
# Parse them
mm = loader.parse_and_check(state, mm_cs, scd_mmm, "Petri-Net Design meta-model")
mm_rt = loader.parse_and_check(state, mm_rt_cs, scd_mmm, "Petri-Net Runtime meta-model")
m = loader.parse_and_check(state, m_cs, mm, "Example model")
m_rt_initial = loader.parse_and_check(state, m_rt_initial_cs, mm_rt, "Example model initial state")
mm_rt_ramified = ramify(state, mm_rt)
rules = loader.load_rules(state,
lambda rule_name, kind: f"{THIS_DIR}/operational_semantics/r_{rule_name}_{kind}.od",
mm_rt_ramified,
["fire_transition"]) # only 1 rule :(
matcher_rewriter = RuleMatcherRewriter(state, mm_rt, mm_rt_ramified)
action_generator = ActionGenerator(matcher_rewriter, rules)
def render_callback(od):
show_petri_net(od)
return render_od(state, od.m, od.mm)
sim = simulator.Simulator(
action_generator=action_generator,
decision_maker=simulator.InteractiveDecisionMaker(auto_proceed=False),
# decision_maker=simulator.RandomDecisionMaker(seed=0),
renderer=render_callback,
# renderer=lambda od: render_od(state, od.m, od.mm),
)
scheduler = RuleScheduler(state, mm_rt, mm_rt_ramified, verbose=True, directory="models")
sim.run(ODAPI(state, m_rt_initial, mm_rt))
# if scheduler.load_schedule(f"petrinet.od"):
# if scheduler.load_schedule("schedules/combinatory.drawio"):
if scheduler.load_schedule("schedules/petrinet3.drawio"):
scheduler.generate_dot("../dot.dot")
code, message = scheduler.run(ODAPI(state, m_rt_initial, mm_rt))
print(f"{code}: {message}")

View file

@ -12,11 +12,22 @@
nameOffsetY="0"
positionX="{{ i * 100 + 100 }}"
positionY="100"
/>
/>
{% endfor %}
{% for i, (transition_name, transition) in enumerate(odapi.get_all_instances("PNTransition")) %}
<transition angle="0" displayName="true" id="{{ transition_name }}" infiniteServer="false" name="{{ transition_name }}" nameOffsetX="0" nameOffsetY="0" player="0" positionX="{{ i * 100 + 100 }}" positionY="300" priority="0" urgent="false"/>
<transition angle="0"
displayName="true"
id="{{ transition_name }}"
infiniteServer="false"
name="{{ transition_name }}"
nameOffsetX="0"
nameOffsetY="0"
player="0"
positionX="{{ i * 100 + 100 }}"
positionY="300"
priority="0"
urgent="false"/>
{% endfor %}
{% for arc_name, arc in odapi.get_all_instances("arc") %}

View file

@ -1,142 +0,0 @@
import functools
from concrete_syntax.common import indent
from examples.semantics.operational.port.helpers import design_to_state, state_to_design, get_time
from examples.semantics.operational.simulator import make_actions_pure, filter_valid_actions
def precondition_can_move_from(od, from_state):
# TO IMPLEMENT
# Function should return True if a ship can move out of 'from_state'
return False
def precondition_can_move_to(od, to_state):
# TO IMPLEMENT
# Function should return True if a ship can move into 'to_state'
return False
def precondition_all_successors_moved(od, conn):
# TO IMPLEMENT
# A move (or skip) can only be made along a connection after all subsequent connections have already made their move (or were skipped).
return True
def precondition_workers_available(od, workerset):
# TO IMPLEMENT
# A worker in a WorkerSet can only be allocated to a berth, if the number of 'isOperating'-links is smaller than the number of workers in the WorkerSet.
return True
def precondition_berth_unserved(od, berth):
# TO IMPLEMENT
# A worker can only be allocated to a berth, if the berth contains an 'unserved' ship.
return True
def action_skip(od, conn_name):
# SERVES AS AN EXAMPLE - NO NEED TO EDIT THIS FUNCTION
conn = od.get(conn_name)
conn_state = design_to_state(od, conn)
od.set_slot_value(conn_state, "moved", True)
return [f"skip {conn_name}"]
def action_move(od, conn_name):
action_skip(od, conn_name) # flag the connection as 'moved'
conn = od.get(conn_name)
from_place = od.get_source(conn)
to_place = od.get_target(conn)
from_state = design_to_state(od, from_place) # beware: Generator does not have State
to_state = design_to_state(od, to_place)
# TO IMPLEMENT:
# - move a ship along the connection
return [f"unimplemented! nothing changed!"]
def action_serve_berth(od, workerset_name, berth_name):
# TO IMPLEMENT:
# - A worker starts operating a berth
return [f"unimplemented! nothing changed!"]
def action_advance_time(od):
_, clock = od.get_all_instances("Clock")[0]
time = od.get_slot_value(clock, "time")
new_time = time + 1
od.set_slot_value(clock, "time", new_time)
# TO IMPLEMENT:
# - all 'moved'-attributes need to be reset (to False)
# - if there is a worker operating a Berth, then:
# (1) the Berth's status becomes 'served'
# (2) the worker is no longer operating the Berth
return [f"time is now {new_time}"]
# This function is called to discover the possible steps that can be made.
# It should not be necessary to edit this function
def get_actions(od):
actions = {}
# Add move-actions (or skip-actions)
for conn_name, conn in od.get_all_instances("connection"):
already_moved = od.get_slot_value(design_to_state(od, conn), "moved")
if already_moved or not precondition_all_successors_moved(od, conn):
# a move was already made along this connection in the current time-step
continue
from_place = od.get_source(conn)
to_place = od.get_target(conn)
from_name = od.get_name(from_place)
to_name = od.get_name(to_place)
from_state = design_to_state(od, from_place)
to_state = design_to_state(od, to_place)
if (precondition_can_move_from(od, from_state)
and precondition_can_move_to(od, to_state)):
actions[f"move {conn_name} ({from_name} -> {to_name})"] = functools.partial(action_move, conn_name=conn_name)
else:
actions[f"skip {from_name} -> {to_name}"] = functools.partial(action_skip, conn_name=conn_name)
# Add actions to assign workers
for _, workerset in od.get_all_instances("WorkerSet"):
if not precondition_workers_available(od, workerset):
continue
for lnk in od.get_outgoing(workerset, "canOperate"):
berth = od.get_target(lnk)
if precondition_berth_unserved(od, berth):
berth_name = od.get_name(berth)
workerset_name = od.get_name(workerset)
actions[f"{workerset_name} operates {berth_name}"] = functools.partial(action_serve_berth, workerset_name=workerset_name, berth_name=berth_name)
# Only when no other action can be performed, can time advance
if len(actions) == 0:
actions["advance time"] = action_advance_time
# This wrapper turns our actions into pure functions: they will clone the model before modifying it. This is useful if we ever want to rollback an action.
return make_actions_pure(actions.items(), od)
# Called every time the runtime state changes.
# When this function returns a string, the simulation ends.
# The string should represent the reason for ending the simulation.
# When this function returns None, the simulation continues.
def termination_condition(od):
# TO IMPLEMENT: terminate simulation when the place 'served' contains 2 ships.
pass

View file

@ -1,18 +0,0 @@
# Some helper functions
def get_num_ships(od, place):
place_state = design_to_state(od, place)
return od.get_slot_value(place_state, "numShips")
def design_to_state(od, design):
incoming = od.get_incoming(design, "of")
if len(incoming) == 1:
# not all design-objects have a state
return od.get_source(incoming[0])
def state_to_design(od, state):
return od.get_target(od.get_outgoing(state, "of")[0])
def get_time(od):
_, clock = od.get_all_instances("Clock")[0]
return clock, od.get_slot_value(clock, "time")

View file

@ -1,407 +0,0 @@
# Design meta-model
port_mm_cs = """
Source:Class {
abstract = True;
}
Sink:Class {
abstract = True;
}
Place:Class
:Inheritance (Place -> Source)
:Inheritance (Place -> Sink)
connection:Association (Source -> Sink)
CapacityConstraint:Class
CapacityConstraint_shipCapacity:AttributeLink (CapacityConstraint -> Integer) {
name = "shipCapacity";
optional = False;
# cannot have negative capacity:
constraint = `get_value(get_target(this)) >= 0`; # non-negative
}
# Capacity
capacityOf:Association (CapacityConstraint -> Place) {
# must say something about at least one Place, otherwise what is the point of the constraint?
target_lower_cardinality = 1;
}
Berth:Class
:Inheritance (Berth -> Place)
# Set of workers
WorkerSet:Class
WorkerSet_numWorkers:AttributeLink (WorkerSet -> Integer) {
name = "numWorkers";
optional = False;
constraint = `get_value(get_target(this)) >= 0`; # non-negative
}
canOperate:Association (WorkerSet -> Berth) {
target_lower_cardinality = 1;
}
Generator:Class
:Inheritance (Generator -> Source)
# Those classes to which we want to attach a runtime state object
Stateful:Class {
abstract = True;
}
:Inheritance (Place -> Stateful)
:Inheritance (WorkerSet -> Stateful)
:Inheritance (Berth -> Stateful)
:Inheritance (connection -> Stateful)
""";
# Runtime meta-model
port_rt_mm_cs = port_mm_cs + """
State:Class
of:Association (State -> Stateful) {
source_lower_cardinality = 1;
source_upper_cardinality = 1;
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}
PlaceState:Class
:Inheritance (PlaceState -> State)
PlaceState_numShips:AttributeLink (PlaceState -> Integer) {
# number of ships currently in the place
name = "numShips";
optional = False;
constraint = `get_value(get_target(this)) >= 0`; # non-negative
}
shipCapacities:GlobalConstraint {
constraint = ```
errors = []
for _, constr in get_all_instances("CapacityConstraint"):
cap = get_slot_value(constr, "shipCapacity")
total = 0
place_names = [] # for debugging
for lnk in get_outgoing(constr, "capacityOf"):
place = get_target(lnk)
place_names.append(get_name(place))
place_state = get_source(get_incoming(place, "of")[0])
total += get_slot_value(place_state, "numShips")
if total > cap:
errors.append(f"The number of ships in places {','.join(place_names)} ({total}) exceeds the capacity ({cap}) of CapacityConstraint {get_name(constr)}.")
errors
```;
}
BerthState:Class {
# status == empty <=> numShips == 0
constraint = ```
errors = []
numShips = get_slot_value(this, "numShips")
status = get_slot_value(this, "status")
if (numShips == 0) != (status == "empty"):
errors.append(f"Inconsistent: numShips = {numShips}, but status = {status}")
errors
```;
}
:Inheritance (BerthState -> PlaceState)
BerthState_status:AttributeLink (BerthState -> String) {
name = "status";
optional = False;
constraint = `(
get_value(get_target(this)) in { "empty", "unserved", "served" }
)`;
}
WorkerSetState:Class
:Inheritance (WorkerSetState -> State)
isOperating:Association (WorkerSetState -> Berth) {
constraint = ```
errors = []
# get status of Berth
berth = get_target(this)
berth_state = get_source(get_incoming(berth, "of")[0])
status = get_slot_value(berth_state, "status")
if status != "unserved":
errors.append(f"Cannot operate {get_name(berth)} because there is no unserved ship there.")
# only operate Berts that we can operate
workerset = get_target(get_outgoing(get_source(this), "of")[0])
can_operate = [get_target(lnk) for lnk in get_outgoing(workerset, "canOperate")]
if berth not in can_operate:
errors.append(f"Cannot operate {get_name(berth)}.")
errors
```;
}
operatingCapacities:GlobalConstraint {
constraint = ```
errors = []
for _, workersetstate in get_all_instances("WorkerSetState"):
workerset = get_target(get_outgoing(workersetstate, "of")[0])
num_operating = len(get_outgoing(workersetstate, "isOperating"))
num_workers = get_slot_value(workerset, "numWorkers")
if num_operating > num_workers:
errors.append(f"WorkerSet {get_name(workerset)} is operating more berths ({num_operating}) than there are workers ({num_workers})")
errors
```;
}
ConnectionState:Class
:Inheritance (ConnectionState -> State)
ConnectionState_moved:AttributeLink (ConnectionState -> Boolean) {
name = "moved";
optional = False;
constraint = ```
result = True
all_successors_moved = True
moved = get_value(get_target(this))
conn_state = get_source(this)
conn = get_target(get_outgoing(conn_state, "of")[0])
tgt_place = get_target(conn)
next_conns = get_outgoing(tgt_place, "connection")
for next_conn in next_conns:
next_conn_state = get_source(get_incoming(next_conn, "of")[0])
if not get_slot_value(next_conn_state, "moved"):
all_successors_moved = False
if moved and not all_successors_moved:
result = f"Connection {get_name(conn)} played before its turn."
result
```;
}
Clock:Class {
lower_cardinality = 1;
upper_cardinality = 1;
}
Clock_time:AttributeLink (Clock -> Integer) {
name = "time";
optional = False;
constraint = `get_value(get_target(this)) >= 0`;
}
"""
# Design model: the part that doesn't change
port_m_cs = """
gen:Generator
# newly arrived ships collect here
waiting:Place
c1:connection (gen -> waiting)
inboundPassage:Place
c2:connection (waiting -> inboundPassage)
outboundPassage:Place
# inboundPassage and outboundPassage cannot have more than 3 ships total
passageCap:CapacityConstraint {
shipCapacity = 3;
}
:capacityOf (passageCap -> inboundPassage)
:capacityOf (passageCap -> outboundPassage)
# Berth 1
inboundBerth1:Place
berth1:Berth
outboundBerth1:Place
inboundBerth1Cap:CapacityConstraint { shipCapacity = 1; }
:capacityOf (inboundBerth1Cap -> inboundBerth1)
outboundBerth1Cap:CapacityConstraint { shipCapacity = 1; }
:capacityOf (outboundBerth1Cap -> outboundBerth1)
berth1Cap:CapacityConstraint { shipCapacity = 1; }
:capacityOf (berth1Cap -> berth1)
c3:connection (inboundBerth1 -> berth1)
c4:connection (berth1 -> outboundBerth1)
# Berth 2
inboundBerth2:Place
berth2:Berth
outboundBerth2:Place
inboundBerth2Cap:CapacityConstraint { shipCapacity = 1; }
:capacityOf (inboundBerth2Cap -> inboundBerth2)
outboundBerth2Cap:CapacityConstraint { shipCapacity = 1; }
:capacityOf (outboundBerth2Cap -> outboundBerth2)
berth2Cap:CapacityConstraint { shipCapacity = 1; }
:capacityOf (berth2Cap -> berth2)
c5:connection (inboundBerth2 -> berth2)
c6:connection (berth2 -> outboundBerth2)
# can either go to Berth 1 or Berth 2
c7:connection (inboundPassage -> inboundBerth1)
c8:connection (inboundPassage -> inboundBerth2)
c9:connection (outboundBerth1 -> outboundPassage)
c10:connection (outboundBerth2 -> outboundPassage)
# ships that have been served are counted here
served:Place
c11:connection (outboundPassage -> served)
workers:WorkerSet {
numWorkers = 1;
}
:canOperate (workers -> berth1)
:canOperate (workers -> berth2)
"""
# Initial runtime model: the part that changes (every execution step)
port_rt_m_cs = port_m_cs + """
clock:Clock {
time = 0;
}
waitingState:PlaceState { numShips = 0; } :of (waitingState -> waiting)
inboundPassageState:PlaceState { numShips = 0; } :of (inboundPassageState -> inboundPassage)
outboundPassageState:PlaceState { numShips = 0; } :of (outboundPassageState -> outboundPassage)
inboundBerth1State:PlaceState { numShips = 0; } :of (inboundBerth1State -> inboundBerth1)
outboundBerth1State:PlaceState { numShips = 0; } :of (outboundBerth1State -> outboundBerth1)
inboundBerth2State:PlaceState { numShips = 0; } :of (inboundBerth2State -> inboundBerth2)
outboundBerth2State:PlaceState { numShips = 0; } :of (outboundBerth2State -> outboundBerth2)
berth1State:BerthState { status = "empty"; numShips = 0; } :of (berth1State -> berth1)
berth2State:BerthState { status = "empty"; numShips = 0; } :of (berth2State -> berth2)
servedState:PlaceState { numShips = 0; } :of (servedState -> served)
workersState:WorkerSetState :of (workersState -> workers)
c1S:ConnectionState { moved = False; } :of (c1S -> c1)
c2S:ConnectionState { moved = False; } :of (c2S -> c2)
c3S:ConnectionState { moved = False; } :of (c3S -> c3)
c4S:ConnectionState { moved = False; } :of (c4S -> c4)
c5S:ConnectionState { moved = False; } :of (c5S -> c5)
c6S:ConnectionState { moved = False; } :of (c6S -> c6)
c7S:ConnectionState { moved = False; } :of (c7S -> c7)
c8S:ConnectionState { moved = False; } :of (c8S -> c8)
c9S:ConnectionState { moved = False; } :of (c9S -> c9)
c10S:ConnectionState { moved = False; } :of (c10S -> c10)
c11S:ConnectionState { moved = False; } :of (c11S -> c11)
"""
###################################################
# ┌─────────────────┐
# │ shipCapacity=3 │
# ┌───┐ ┌───────┐ │┌──────────────┐ │ ┌───────┐
# │gen├────►│waiting├────►│inboundPassage├───►│turning│
# └───┘ └───────┘ │└──────────────┘ │ └───┬───┘
# │ │ │
# ┌──────┐ │┌───────────────┐│ │
# │served│◄────┼outboundPassage│◄──────┘
# └──────┘ │└───────────────┘│
# └─────────────────┘
smaller_model_cs = """
gen:Generator
waiting:Place
inboundPassage:Place
turning:Place
outboundPassage:Place
served:Place
gen2wait:connection (gen -> waiting)
wait2inbound:connection (waiting -> inboundPassage)
inbound2turning:connection (inboundPassage -> turning)
turning2outbound:connection (turning -> outboundPassage)
outbound2served:connection (outboundPassage -> served)
# inboundPassage and outboundPassage cannot have more than 3 ships total
passageCap:CapacityConstraint {
shipCapacity = 3;
}
:capacityOf (passageCap -> inboundPassage)
:capacityOf (passageCap -> outboundPassage)
"""
smaller_model_rt_cs = smaller_model_cs + """
clock:Clock {
time = 0;
}
waitingState:PlaceState { numShips = 1; } :of (waitingState -> waiting)
inboundPassageState:PlaceState { numShips = 1; } :of (inboundPassageState -> inboundPassage)
turningState:PlaceState { numShips = 1; } :of (turningState -> turning)
outboundPassageState:PlaceState { numShips = 1; } :of (outboundPassageState -> outboundPassage)
servedState:PlaceState { numShips = 0; } :of (servedState -> served)
gen2waitState:ConnectionState { moved = False; } :of (gen2waitState -> gen2wait)
wait2inboundState:ConnectionState { moved = False; } :of (wait2inboundState -> wait2inbound)
inbound2turningState:ConnectionState { moved = False; } :of (inbound2turningState -> inbound2turning)
turning2outboundState:ConnectionState { moved = False; } :of (turning2outboundState -> turning2outbound)
outbound2servedState:ConnectionState { moved = False; } :of (outbound2servedState -> outbound2served)
"""
###################################################
# ┌────────────┐
# │ workerset │
# │ │
# │numWorkers=1│
# └──────┬─────┘
# │canOperate
# │
# ┌───▼────┐
# ┌───┐ ┌───────┐ │┌─────┐ │ ┌──────┐
# │gen├────►│waiting├────││berth├─┼───►│served│
# └───┘ └───────┘ │└─────┘ │ └──────┘
# │ship- │
# │Capacity│
# │ =1 │
# └────────┘
smaller_model2_cs = """
gen:Generator
waiting:Place
berth:Berth
served:Place
gen2wait:connection (gen -> waiting)
wait2berth:connection (waiting -> berth)
berth2served:connection (berth -> served)
# berth can only hold 1 ship
passageCap:CapacityConstraint {
shipCapacity = 1;
}
:capacityOf (passageCap -> berth)
workers:WorkerSet {
numWorkers = 1;
}
:canOperate (workers -> berth)
"""
smaller_model2_rt_cs = smaller_model2_cs + """
clock:Clock {
time = 0;
}
waitingState:PlaceState { numShips = 1; } :of (waitingState -> waiting)
berthState:BerthState { numShips = 0; status = "empty"; } :of (berthState -> berth)
servedState:PlaceState { numShips = 0; } :of (servedState -> served)
gen2waitState:ConnectionState { moved = False; } :of (gen2waitState -> gen2wait)
wait2berthState:ConnectionState { moved = False; } :of (wait2berthState -> wait2berth)
berth2servedState:ConnectionState { moved = False; } :of (berth2servedState -> berth2served)
workersState:WorkerSetState :of (workersState -> workers)
"""

View file

@ -1,78 +0,0 @@
from concrete_syntax.common import indent
from concrete_syntax.graphviz.make_url import make_url
from examples.semantics.operational.port.helpers import design_to_state, state_to_design, get_time, get_num_ships
def render_port_to_dot(od,
make_id=lambda name,obj: name # by default, we just use the object name for the graphviz node name
):
txt = ""
def render_place(place):
name = od.get_name(place)
return f'"{make_id(name,place)}" [ label = "{name}\\n ships = {get_num_ships(od, place)}", style = filled, fillcolor = lightblue ]\n'
for _, cap in od.get_all_instances("CapacityConstraint", include_subtypes=False):
name = od.get_name(cap)
capacity = od.get_slot_value(cap, "shipCapacity")
txt += f'subgraph cluster_{name} {{\n label = "{name}\\n capacity = {capacity}";\n'
for lnk in od.get_outgoing(cap, "capacityOf"):
place = od.get_target(lnk)
txt += f' {render_place(place)}'
txt += f'}}\n'
for _, place_state in od.get_all_instances("PlaceState", include_subtypes=False):
place = state_to_design(od, place_state)
if len(od.get_incoming(place, "capacityOf")) == 0:
txt += render_place(place)
for _, berth_state in od.get_all_instances("BerthState", include_subtypes=False):
berth = state_to_design(od, berth_state)
name = od.get_name(berth)
txt += f'"{make_id(name,berth)}" [ label = "{name}\\n numShips = {get_num_ships(od, berth)}\\n status = {od.get_slot_value(berth_state, "status")}", fillcolor = yellow, style = filled]\n'
for _, gen in od.get_all_instances("Generator", include_subtypes=False):
txt += f'"{make_id(od.get_name(gen),gen)}" [ label = "+", shape = diamond, fillcolor = green, fontsize = 30, style = filled ]\n'
for _, conn in od.get_all_instances("connection"):
src = od.get_source(conn)
tgt = od.get_target(conn)
moved = od.get_slot_value(design_to_state(od, conn), "moved")
src_name = od.get_name(src)
tgt_name = od.get_name(tgt)
txt += f"{make_id(src_name,src)} -> {make_id(tgt_name,tgt)} [color=deepskyblue3, penwidth={1 if moved else 2}];\n"
for _, workers in od.get_all_instances("WorkerSet"):
already_have = []
name = od.get_name(workers)
num_workers = od.get_slot_value(workers, "numWorkers")
txt += f'{make_id(name,workers)} [label="{num_workers} worker(s)", shape=parallelogram, fillcolor=chocolate, style=filled];\n'
for lnk in od.get_outgoing(design_to_state(od, workers), "isOperating"):
berth = od.get_target(lnk)
already_have.append(berth)
txt += f"{make_id(name,workers)} -> {make_id(od.get_name(berth),berth)} [arrowhead=none, color=chocolate];\n"
for lnk in od.get_outgoing(workers, "canOperate"):
berth = od.get_target(lnk)
if berth not in already_have:
txt += f"{make_id(name,workers)} -> {make_id(od.get_name(berth),berth)} [style=dotted, arrowhead=none, color=chocolate];\n"
return txt
def render_port_graphviz(od):
return make_url(render_port_to_dot(od))
def render_port_textual(od):
txt = ""
for _, place_state in od.get_all_instances("PlaceState", include_subtypes=False):
place = state_to_design(od, place_state)
name = od.get_name(place)
txt += f'place "{name}" {"🚢"*get_num_ships(od, place)}\n'
for _, berth_state in od.get_all_instances("BerthState", include_subtypes=False):
berth = state_to_design(od, berth_state)
name = od.get_name(berth)
operated_descr = ""
if len(od.get_incoming(berth, "isOperating")):
operated_descr = " and being operated"
txt += f'berth "{name}" {"🚢"*get_num_ships(od, berth)} {od.get_slot_value(berth_state, "status")}{operated_descr}\n'
return txt

View file

@ -1,62 +0,0 @@
import urllib.parse
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from framework.conformance import Conformance, render_conformance_check_result
from concrete_syntax.textual_od import parser
from concrete_syntax.plantuml.renderer import render_object_diagram, render_class_diagram
from api.od import ODAPI
from transformation.ramify import ramify
from examples.semantics.operational.simulator import Simulator, RandomDecisionMaker, InteractiveDecisionMaker
from examples.semantics.operational.port import models
from examples.semantics.operational.port.helpers import design_to_state, state_to_design, get_time
from examples.semantics.operational.port.renderer import render_port_textual, render_port_graphviz
from examples.semantics.operational.port import rulebased_sem
state = DevState()
scd_mmm = bootstrap_scd(state) # Load meta-meta-model
### Load (meta-)models ###
def parse_and_check(m_cs: str, mm, descr: str):
m = parser.parse_od(
state,
m_text=m_cs,
mm=mm)
conf = Conformance(state, m, mm)
print(descr, "...", render_conformance_check_result(conf.check_nominal()))
return m
port_mm = parse_and_check(models.port_mm_cs, scd_mmm, "MM")
port_m = parse_and_check(models.port_m_cs, port_mm, "M")
port_rt_mm = parse_and_check(models.port_rt_mm_cs, scd_mmm, "RT-MM")
port_rt_m = parse_and_check(models.port_rt_m_cs, port_rt_mm, "RT-M")
print()
# print(render_class_diagram(state, port_rt_mm))
### Simulate ###
port_rt_mm_ramified = ramify(state, port_rt_mm)
rulebased_action_generator = rulebased_sem.get_action_generator(state, port_rt_mm, port_rt_mm_ramified)
termination_condition = rulebased_sem.TerminationCondition(state, port_rt_mm_ramified)
sim = Simulator(
action_generator=rulebased_action_generator,
# decision_maker=RandomDecisionMaker(seed=2),
decision_maker=InteractiveDecisionMaker(),
termination_condition=termination_condition,
check_conformance=True,
verbose=True,
renderer=render_port_textual,
# renderer=render_port_graphviz,
)
od = ODAPI(state, port_rt_m, port_rt_mm)
sim.run(od)

View file

@ -1,67 +0,0 @@
### Operational Semantics - defined by rule-based model transformation ###
from concrete_syntax.textual_od.parser import parse_od
from transformation.rule import Rule, RuleMatcherRewriter, PriorityActionGenerator
from transformation.matcher import match_od
from util import loader
import os
THIS_DIR = os.path.dirname(__file__)
# kind: lhs, rhs, nac
get_filename = lambda rule_name, kind: f"{THIS_DIR}/rules/r_{rule_name}_{kind}.od"
def get_action_generator(state, rt_mm, rt_mm_ramified):
matcher_rewriter = RuleMatcherRewriter(state, rt_mm, rt_mm_ramified)
#############################################################################
# TO IMPLEMENT: Full semantics as a set of rule-based model transformations #
rules0_dict = loader.load_rules(state, get_filename, rt_mm_ramified,
["ship_sinks"] # <- list of rule_name of equal priority
)
rules1_dict = loader.load_rules(state, get_filename, rt_mm_ramified,
["ship_appears_in_berth"]
)
# rules2_dict = ...
generator = PriorityActionGenerator(matcher_rewriter, [
rules0_dict, # highest priority
rules1_dict, # lower priority
# rules2_dict, # lowest priority
])
# TO IMPLEMENT: Full semantics as a set of rule-based model transformations #
#############################################################################
return generator
# The termination condition can also be specified as a pattern:
class TerminationCondition:
def __init__(self, state, rt_mm_ramified):
self.state = state
self.rt_mm_ramified = rt_mm_ramified
# TO IMPLEMENT: terminate simulation when the place 'served' contains 2 ships.
########################################
# You should only edit the pattern below
pattern_cs = """
# Placeholder to make the termination condition never hold:
:GlobalCondition {
condition = `False`;
}
"""
# You should only edit the pattern above
########################################
self.pattern = parse_od(state, pattern_cs, rt_mm_ramified)
def __call__(self, od):
for match in match_od(self.state, od.m, od.mm, self.pattern, self.rt_mm_ramified):
# stop after the first match (no need to look for more matches):
return "There are 2 ships served." # Termination condition statisfied

View file

@ -1,13 +0,0 @@
The names of the files in this directory are important.
A rule must always be named:
r_<rule_name>_<lhs|rhs|nac>.od
It is allowed to have more than one NAC. In this case, the NACs must be named:
r_<rule_name>_nac.od
r_<rule_name>_nac2.od
r_<rule_name>_nac3.od
...
For the assignment, you can delete the existing rules (they are nonsense) and start fresh.

View file

@ -1,4 +0,0 @@
berthState:RAM_BerthState {
RAM_numShips = `get_value(this) == 0`;
RAM_status = `get_value(this) == "empty"`;
}

View file

@ -1,4 +0,0 @@
berthState:RAM_BerthState {
RAM_numShips = `1`;
RAM_status = `"served"`;
}

View file

@ -1,5 +0,0 @@
# Find any place that has at least one ship:
placeState:RAM_PlaceState {
RAM_numShips = `get_value(this) > 0`;
}

View file

@ -1,4 +0,0 @@
placeState:RAM_PlaceState {
# Decrement number of ships:
RAM_numShips = `get_value(this) - 1`;
}

View file

@ -1,56 +0,0 @@
import urllib.parse
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from framework.conformance import Conformance, render_conformance_check_result
from concrete_syntax.textual_od import parser
from concrete_syntax.plantuml.renderer import render_object_diagram, render_class_diagram
from api.od import ODAPI
from examples.semantics.operational.simulator import Simulator, RandomDecisionMaker, InteractiveDecisionMaker
from examples.semantics.operational.port import models
from examples.semantics.operational.port.helpers import design_to_state, state_to_design, get_time
from examples.semantics.operational.port.renderer import render_port_textual, render_port_graphviz
# from examples.semantics.operational.port.joeris_solution import termination_condition, get_actions
from examples.semantics.operational.port.assignment import termination_condition, get_actions
state = DevState()
scd_mmm = bootstrap_scd(state) # Load meta-meta-model
### Load (meta-)models ###
def parse_and_check(m_cs: str, mm, descr: str):
m = parser.parse_od(
state,
m_text=m_cs,
mm=mm)
conf = Conformance(state, m, mm)
print(descr, "...", render_conformance_check_result(conf.check_nominal()))
return m
port_mm = parse_and_check(models.port_mm_cs, scd_mmm, "MM")
port_m = parse_and_check(models.port_m_cs, port_mm, "M")
port_rt_mm = parse_and_check(models.port_rt_mm_cs, scd_mmm, "RT-MM")
port_rt_m = parse_and_check(models.port_rt_m_cs, port_rt_mm, "RT-M")
print()
# print(render_class_diagram(state, port_rt_mm))
### Simulate ###
sim = Simulator(
action_generator=get_actions,
# decision_maker=RandomDecisionMaker(seed=2),
decision_maker=InteractiveDecisionMaker(),
termination_condition=termination_condition,
check_conformance=True,
verbose=True,
renderer=render_port_textual,
# renderer=render_port_graphviz,
)
od = ODAPI(state, port_rt_m, port_rt_mm)
sim.run(od)

View file

@ -1,70 +0,0 @@
import abc
import random
import math
import functools
import sys
from framework.conformance import Conformance, render_conformance_check_result
from concrete_syntax.common import indent
from concrete_syntax.textual_od.renderer import render_od
from transformation.cloner import clone_od
from api.od import ODAPI
from util.simulator import MinimalSimulator, DecisionMaker, RandomDecisionMaker, InteractiveDecisionMaker
class Simulator(MinimalSimulator):
def __init__(self,
action_generator,
decision_maker: DecisionMaker,
termination_condition=lambda od: None,
check_conformance=True,
verbose=True,
renderer=lambda od: render_od(od.state, od.m, od.mm),
):
super().__init__(
action_generator=action_generator,
decision_maker=decision_maker,
termination_condition=lambda od: self.check_render_termination_condition(od),
verbose=verbose,
)
self.check_conformance = check_conformance
self.actual_termination_condition = termination_condition
self.renderer = renderer
def check_render_termination_condition(self, od):
# A termination condition checker that also renders the model, and performs conformance check
self._print("--------------")
self._print(indent(self.renderer(od), 2))
self._print("--------------")
if self.check_conformance:
conf = Conformance(od.state, od.m, od.mm)
self._print(render_conformance_check_result(conf.check_nominal()))
self._print()
return self.actual_termination_condition(od)
def make_actions_pure(actions, od):
# Copy model before modifying it
def exec_pure(action, od):
cloned_rt_m = clone_od(od.state, od.m, od.mm)
new_od = ODAPI(od.state, cloned_rt_m, od.mm)
msgs = action(new_od)
return (new_od, msgs)
for descr, action in actions:
yield (descr, functools.partial(exec_pure, action, od))
def filter_valid_actions(pure_actions):
result = {}
def make_tuple(new_od, msgs):
return (new_od, msgs)
for name, callback in pure_actions:
# print(f"attempt '{name}' ...", end='\r')
(new_od, msgs) = callback()
conf = Conformance(new_od.state, new_od.m, new_od.mm)
errors = conf.check_nominal()
# erase current line:
# print(" ", end='\r')
if len(errors) == 0:
# updated RT-M is conform, we have a valid action:
yield (name, functools.partial(make_tuple, new_od, msgs))

View file

@ -1,4 +0,0 @@
# Let's not accidently add the solution to assignment 5...
r_*.od
snapshot_after_*.od

View file

@ -1,197 +0,0 @@
# Auto-generated by /home/maestro/repos/MV2/examples/semantics/translational/regenerate_mm.py.
# Merged run-time meta-models of 'Petri Net' and 'Port' formalisms.
# An abstract 'Top'-class (superclass of everything else), and a 'generic_link'-association (which can connect everything with everything) have also been added.
# PlantUML visualization: https://deemz.org/plantuml/pdf/hPTFYzim4CNl_XGYnqA27P8uDgM7tSEobsmWWHw3RCk9Y2CPMIcKThzxHyuViiMGPwCSzhJpqxoPfz4uo2lUD6pqockUI_lxLQl66YwLPIF66nPUVxkEF-ut2uk8_GaOQmwola5OojwL5NjXWi_WUi1wjQvuBZQMMm6ZborQdKzRVHIgwUB-rEOep4RW-POtw2MqazehJR4WucV0CrUvtB97HdckO4pHZT5dawEvH25l8RUkLZe_icWoYS3mQTmMnygJw2hBYp3sqASsqPnVt44nPrVfZJLIxJjaRdMDCkFuKMDhApGqcJs6thtJIrAIFJBQag2XVFeO-YQKCDng0uSdNuIljeQhHbgf5Kh8mawFhLTqxvN8BSygk0vPtErNgOueelZIZciE9ATNFyhB03hfNtI3KlQYTIMu-iyW_OZtkREXgTOv8AxZ32QMhT3WwN-wAV3zxtZyd3ahn7ESkoiOZkQuJnorrYTkFaDmTBl1xFZKPoleJG6oez4CPfS0Ojsh0-BAfLUZY8LNeuJSAsuQ-nLR-3GArDaUOZD0R0-Z91cGNG5VCaWipLeGDqUCak6r2_rUCg_ZarPVhnE59rvjZ8pF7gqeI-XbNB1Hn2OJHiliUFo3djuHjbMdJ2FpcV9ro1OTkdE-0NmNbJ9kSa00VNdS3uZW0sXdJ5dErKVjbaNapI_BGK92EaUgmmuIuxmtu10Q7YJclkSXHLiEwBehGSfgjOCQ7mzgVEmQltShlCnt5Iszo8AI3JcfTO1iBWPmNqz0rQ8XLalQxbm_uZ_AVm==
CapacityConstraint:Class
PNPlaceState:Class
WorkerSet:Class
State:Class
Stateful:Class {
abstract = True;
}
Source:Class {
abstract = True;
}
Clock:Class {
lower_cardinality = 1;
upper_cardinality = 1;
}
BerthState:Class {
constraint = ```
errors = []
numShips = get_slot_value(this, "numShips")
status = get_slot_value(this, "status")
if (numShips == 0) != (status == "empty"):
errors.append(f"Inconsistent: numShips = {numShips}, but status = {status}")
errors
```;
}
Top:Class {
abstract = True;
}
Place:Class
WorkerSetState:Class
Berth:Class
Generator:Class
PNTransition:Class
PNConnectable:Class {
abstract = True;
}
Sink:Class {
abstract = True;
}
ConnectionState:Class
PlaceState:Class
PNPlace:Class
shipCapacities:GlobalConstraint {
constraint = ```
errors = []
for _, constr in get_all_instances("CapacityConstraint"):
cap = get_slot_value(constr, "shipCapacity")
total = 0
place_names = [] # for debugging
for lnk in get_outgoing(constr, "capacityOf"):
place = get_target(lnk)
place_names.append(get_name(place))
place_state = get_source(get_incoming(place, "of")[0])
total += get_slot_value(place_state, "numShips")
if total > cap:
errors.append(f"The number of ships in places {','.join(place_names)} ({total}) exceeds the capacity ({cap}) of CapacityConstraint {get_name(constr)}.")
errors
```;
}
operatingCapacities:GlobalConstraint {
constraint = ```
errors = []
for _, workersetstate in get_all_instances("WorkerSetState"):
workerset = get_target(get_outgoing(workersetstate, "of")[0])
num_operating = len(get_outgoing(workersetstate, "isOperating"))
num_workers = get_slot_value(workerset, "numWorkers")
if num_operating > num_workers:
errors.append(f"WorkerSet {get_name(workerset)} is operating more berths ({num_operating}) than there are workers ({num_workers})")
errors
```;
}
WorkerSet_numWorkers:AttributeLink (WorkerSet -> Integer) {
name = "numWorkers";
constraint = `get_value(get_target(this)) >= 0`;
optional = False;
}
PlaceState_numShips:AttributeLink (PlaceState -> Integer) {
constraint = `get_value(get_target(this)) >= 0`;
optional = False;
name = "numShips";
}
ConnectionState_moved:AttributeLink (ConnectionState -> Boolean) {
name = "moved";
constraint = ```
result = True
all_successors_moved = True
moved = get_value(get_target(this))
conn_state = get_source(this)
conn = get_target(get_outgoing(conn_state, "of")[0])
tgt_place = get_target(conn)
next_conns = get_outgoing(tgt_place, "connection")
for next_conn in next_conns:
next_conn_state = get_source(get_incoming(next_conn, "of")[0])
if not get_slot_value(next_conn_state, "moved"):
all_successors_moved = False
if moved and not all_successors_moved:
result = f"Connection {get_name(conn)} played before its turn."
result
```;
optional = False;
}
BerthState_status:AttributeLink (BerthState -> String) {
optional = False;
name = "status";
constraint = ```
(
get_value(get_target(this)) in { "empty", "unserved", "served" }
)
```;
}
PNPlaceState_numTokens:AttributeLink (PNPlaceState -> Integer) {
name = "numTokens";
constraint = `"numTokens cannot be negative" if get_value(get_target(this)) < 0 else None`;
optional = False;
}
Clock_time:AttributeLink (Clock -> Integer) {
optional = False;
name = "time";
constraint = `get_value(get_target(this)) >= 0`;
}
CapacityConstraint_shipCapacity:AttributeLink (CapacityConstraint -> Integer) {
optional = False;
name = "shipCapacity";
constraint = `get_value(get_target(this)) >= 0`;
}
of:Association (State -> Stateful) {
target_lower_cardinality = 1;
source_upper_cardinality = 1;
source_lower_cardinality = 1;
target_upper_cardinality = 1;
}
arc:Association (PNConnectable -> PNConnectable)
canOperate:Association (WorkerSet -> Berth) {
target_lower_cardinality = 1;
}
inh_arc:Association (PNPlace -> PNTransition)
connection:Association (Source -> Sink)
pn_of:Association (PNPlaceState -> PNPlace) {
source_upper_cardinality = 1;
source_lower_cardinality = 1;
target_upper_cardinality = 1;
target_lower_cardinality = 1;
}
generic_link:Association (Top -> Top)
isOperating:Association (WorkerSetState -> Berth) {
constraint = ```
errors = []
# get status of Berth
berth = get_target(this)
berth_state = get_source(get_incoming(berth, "of")[0])
status = get_slot_value(berth_state, "status")
if status != "unserved":
errors.append(f"Cannot operate {get_name(berth)} because there is no unserved ship there.")
# only operate Berts that we can operate
workerset = get_target(get_outgoing(get_source(this), "of")[0])
can_operate = [get_target(lnk) for lnk in get_outgoing(workerset, "canOperate")]
if berth not in can_operate:
errors.append(f"Cannot operate {get_name(berth)}.")
errors
```;
}
capacityOf:Association (CapacityConstraint -> Place) {
target_lower_cardinality = 1;
}
:Inheritance (connection -> Stateful)
:Inheritance (CapacityConstraint -> Top)
:Inheritance (Sink -> Top)
:Inheritance (generic_link -> Top)
:Inheritance (Berth -> Place)
:Inheritance (WorkerSet -> Stateful)
:Inheritance (Place -> Source)
:Inheritance (PlaceState -> State)
:Inheritance (State -> Top)
:Inheritance (Source -> Top)
:Inheritance (Clock -> Top)
:Inheritance (Stateful -> Top)
:Inheritance (Place -> Stateful)
:Inheritance (PNConnectable -> Top)
:Inheritance (WorkerSetState -> State)
:Inheritance (Place -> Sink)
:Inheritance (BerthState -> PlaceState)
:Inheritance (PNTransition -> PNConnectable)
:Inheritance (ConnectionState -> State)
:Inheritance (PNPlaceState -> Top)
:Inheritance (Generator -> Source)
:Inheritance (Berth -> Stateful)
:Inheritance (PNPlace -> PNConnectable)

View file

@ -1,65 +0,0 @@
from state.devstate import DevState
from bootstrap.scd import bootstrap_scd
from concrete_syntax.textual_od import renderer
from concrete_syntax.plantuml.renderer import render_class_diagram
from concrete_syntax.plantuml.make_url import make_url
from api.od import ODAPI
from transformation.topify.topify import Topifier
from transformation.merger import merge_models
from util import loader
from examples.semantics.operational.port import models
import os
THIS_DIR = os.path.dirname(__file__)
# get file contents as string
def read_file(filename):
with open(THIS_DIR+'/'+filename) as file:
return file.read()
if __name__ == "__main__":
state = DevState()
scd_mmm = bootstrap_scd(state)
# Load Petri Net meta-models
pn_mm_cs = read_file('../../petrinet/metamodels/mm_design.od')
pn_mm_rt_cs = pn_mm_cs + read_file('../../petrinet/metamodels/mm_runtime.od')
pn_mm = loader.parse_and_check(state, pn_mm_cs, scd_mmm, "Petri-Net Design meta-model")
pn_mm_rt = loader.parse_and_check(state, pn_mm_rt_cs, scd_mmm, "Petri-Net Runtime meta-model")
# Load Port meta-models
port_mm = loader.parse_and_check(state, models.port_mm_cs, scd_mmm, "Port-MM")
port_mm_rt = loader.parse_and_check(state, models.port_rt_mm_cs, scd_mmm, "Port-MM-RT")
# Merge Petri Net and Port meta-models
print("merging...")
merged_mm_rt = merge_models(state, mm=scd_mmm, models=[pn_mm_rt, port_mm_rt])
print("done merging")
print()
print("topifying... (may take a while)")
topifier = Topifier(state)
top_merged_mm_rt = topifier.topify_cd(merged_mm_rt)
print("done topifying")
plantuml_url = make_url(render_class_diagram(state, top_merged_mm_rt))
print()
print(plantuml_url)
print()
txt = renderer.render_od(state, top_merged_mm_rt, scd_mmm)
filename = THIS_DIR+"/merged_mm.od"
with open(filename, "w") as file:
file.write(f"# Auto-generated by {__file__}.\n\n")
file.write(f"# Merged run-time meta-models of 'Petri Net' and 'Port' formalisms.\n")
file.write(f"# An abstract 'Top'-class (superclass of everything else), and a 'generic_link'-association (which can connect everything with everything) have also been added.\n\n")
file.write(f"# PlantUML visualization: {plantuml_url}\n\n")
file.write(txt)
print("Wrote file", filename)

View file

@ -1,90 +0,0 @@
from api.od import ODAPI
from concrete_syntax.graphviz.renderer import render_object_diagram, make_graphviz_id
from concrete_syntax.graphviz.make_url import show_graphviz
from examples.petrinet.renderer import render_petri_net_to_dot
from examples.semantics.operational.port.renderer import render_port_to_dot
from examples.semantics.operational.port import helpers
# COLORS
PLACE_BG = "#DAE8FC" # fill color
PLACE_FG = "#6C8EBF" # font, line, arrow
BERTH_BG = "#FFF2CC"
BERTH_FG = "#D6B656"
CAPACITY_BG = "#F5F5F5"
CAPACITY_FG = "#666666"
WORKER_BG = "#D5E8D4"
WORKER_FG = "#82B366"
GENERATOR_BG = "#FFE6CC"
GENERATOR_FG = "#D79B00"
CLOCK_BG = "black"
CLOCK_FG = "white"
def graphviz_style_fg_bg(fg, bg):
return f"style=filled,fillcolor=\"{bg}\",color=\"{fg}\",fontcolor=\"{fg}\""
def render_port(state, m, mm):
dot = render_object_diagram(state, m, mm,
reify=True,
only_render=[
# Only render these types
"Place", "Berth", "CapacityConstraint", "WorkerSet", "Generator", "Clock",
"connection", "capacityOf", "canOperate", "generic_link",
# Petri Net types not included (they are already rendered by other function)
# Port-State-types not included to avoid cluttering the diagram, but if you need them, feel free to add them.
],
# We can style nodes/edges according to their type:
type_to_style={
"Place": graphviz_style_fg_bg(PLACE_FG, PLACE_BG),
"Berth": graphviz_style_fg_bg(BERTH_FG, BERTH_BG),
"CapacityConstraint": graphviz_style_fg_bg(CAPACITY_FG, CAPACITY_BG),
"WorkerSet": "shape=oval,"+graphviz_style_fg_bg(WORKER_FG, WORKER_BG),
"Generator": "shape=parallelogram,"+graphviz_style_fg_bg(GENERATOR_FG, GENERATOR_BG),
"Clock": graphviz_style_fg_bg(CLOCK_FG, CLOCK_BG),
# same blue as Place, thick line:
"connection": f"color=\"{PLACE_FG}\",fontcolor=\"{PLACE_FG}\",penwidth=2.0",
# same grey as CapacityConstraint
"capacityOf": f"color=\"{CAPACITY_FG}\",fontcolor=\"{CAPACITY_FG}\"",
# same green as WorkerSet
"canOperate": f"color=\"{WORKER_FG}\",fontcolor=\"{WORKER_FG}\"",
# purple line
"generic_link": "color=purple,fontcolor=purple,arrowhead=onormal",
},
# We have control over the node/edge labels that are rendered:
type_to_label={
"CapacityConstraint": lambda capconstr_name, capconstr, odapi: f"{capconstr_name}\\nshipCapacity={odapi.get_slot_value(capconstr, "shipCapacity")}",
"Place": lambda place_name, place, odapi: f"{place_name}\\nnumShips={helpers.get_num_ships(odapi, place)}",
"Berth": lambda berth_name, berth, odapi: f"{berth_name}\\nnumShips={helpers.get_num_ships(odapi, berth)}\\nstatus={odapi.get_slot_value(helpers.design_to_state(odapi, berth), "status")}",
"Clock": lambda _, clock, odapi: f"Clock\\ntime={odapi.get_slot_value(clock, "time")}",
"connection": lambda conn_name, conn, odapi: f"{conn_name}\\nmoved={odapi.get_slot_value(helpers.design_to_state(odapi, conn), "moved")}",
# hide generic link labels
"generic_link": lambda lnk_name, lnk, odapi: "",
"WorkerSet": lambda ws_name, ws, odapi: f"{ws_name}\\nnumWorkers={odapi.get_slot_value(ws, "numWorkers")}",
# hide the type (it's already clear enough)
"Generator": lambda gen_name, gen, odapi: gen_name,
},
)
return dot
def render_port_and_petri_net(state, m, mm):
od = ODAPI(state, m, mm)
dot = ""
dot += "// petri net:\n"
dot += render_petri_net_to_dot(od)
dot += "\n// the rest:\n"
dot += render_port(state, m, mm)
return dot
def show_port_and_petri_net(state, m, mm, engine="dot"):
show_graphviz(render_port_and_petri_net(state, m, mm), engine=engine)

Some files were not shown because too many files have changed in this diff Show more