A fully working version of the scheduling language with added examples

This commit is contained in:
robbe 2025-06-27 12:21:41 +02:00
parent ec42f74960
commit ebfd85a666
126 changed files with 7235 additions and 981 deletions

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 = RuleSchedular(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

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,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

@ -1,66 +0,0 @@
start:Start
end:End
transitions:Match{
file = "operational_semantics/transition";
}
d:Data_modify
{
modify_dict = '
{
"tr": "t"
}';
}
nac_input_without:Match{
file = "operational_semantics/all_input_have_token";
n = "1";
}
inputs:Match{
file = "operational_semantics/all_inputs";
}
rewrite_incoming:Rewrite
{
file = "operational_semantics/remove_incoming";
}
loop_trans:Loop
loop_input:Loop
p:Print
{
event = True;
label = "transition: ";
}
p2:Print
{
event = True;
label = "inputs: ";
}
:Exec_con(start -> transitions){gate_from = 0;gate_to = 0;}
:Exec_con(transitions -> end){gate_from = 1;gate_to = 0;}
:Exec_con(transitions -> loop_trans){gate_from = 0;gate_to = 0;}
:Exec_con(loop_trans -> nac_input_without){gate_from = 0;gate_to = 0;}
[//]: # (:Exec_con&#40;nac_input_without -> loop_trans&#41;{gate_from = 0;gate_to = 0;})
:Exec_con(nac_input_without -> inputs){gate_from = 1;gate_to = 0;}
:Exec_con(inputs -> loop_input){gate_from = 0;gate_to = 0;}
:Exec_con(inputs -> loop_trans){gate_from = 1;gate_to = 0;}
:Exec_con(loop_trans -> end){gate_from = 1;gate_to = 0;}
:Data_con(transitions -> loop_trans)
:Data_con(nac_input_without -> p)
:Data_con(d -> nac_input_without)
:Data_con(loop_trans -> d)
:Data_con(loop_trans -> rewrite_incoming)

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,23 @@
start:Start {
ports_exec = `["F","FF"]`;
}
end:End {
ports_exec = `["F"]`;
}
p1:Print{
custom = "Foo";
}
p2:Print{
custom = "FooFoo";
}
p3:Print{
custom = "FooFooFoo";
}
:Conn_exec (start -> p1) {from="F";to="in";}
:Conn_exec (p1 -> end) {from="out";to="F";}
:Conn_exec (start -> p2) {from="FF";to="in";}
:Conn_exec (p2 -> end) {from="out";to="F";}

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,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 = `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 @@
tr:RAM_PNTransition
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,19 +1,12 @@
from examples.schedule.RuleExecuter import RuleExecuter
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 examples.schedule.ScheduledActionGenerator import *
from examples.schedule.RuleExecuter import *
from transformation.schedule.rule_scheduler import *
if __name__ == "__main__":
import os
@ -35,40 +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)
matcher_rewriter2 = RuleExecuter(state, mm_rt, mm_rt_ramified)
action_generator = ScheduleActionGenerator(matcher_rewriter2, f"models/schedule.od")
def render_callback(od):
show_petri_net(od)
return render_od(state, od.m, od.mm)
action_generator = RuleSchedular(state, mm_rt, mm_rt_ramified, verbose=True, directory="models")
action_generator.generate_dot()
# if action_generator.load_schedule(f"petrinet.od"):
# if action_generator.load_schedule("schedules/combinatory.drawio"):
if action_generator.load_schedule("schedules/petrinet3.drawio"):
sim = simulator.MinimalSimulator(
action_generator=action_generator,
decision_maker=simulator.InteractiveDecisionMaker(auto_proceed=False),
# decision_maker=simulator.RandomDecisionMaker(seed=0),
termination_condition=action_generator.termination_condition,
# renderer=lambda od: render_od(state, od.m, od.mm),
)
sim.run(ODAPI(state, m_rt_initial, mm_rt))
action_generator.generate_dot("../dot.dot")
code, message = action_generator.run(ODAPI(state, m_rt_initial, mm_rt))
print(f"{code}: {message}")

View file

@ -1,49 +0,0 @@
from concrete_syntax.textual_od.renderer import render_od
import pprint
from typing import Generator, Callable, Any
from uuid import UUID
import functools
from api.od import ODAPI
from concrete_syntax.common import indent
from transformation.matcher import match_od
from transformation.rewriter import rewrite
from transformation.cloner import clone_od
from util.timer import Timer
from util.loader import parse_and_check
class RuleExecuter:
def __init__(self, state, mm: UUID, mm_ramified: UUID, eval_context={}):
self.state = state
self.mm = mm
self.mm_ramified = mm_ramified
self.eval_context = eval_context
# Generates matches.
# Every match is a dictionary with entries LHS_element_name -> model_element_name
def match_rule(self, m: UUID, lhs: UUID, *, pivot:dict[Any, Any]):
lhs_matcher = match_od(self.state,
host_m=m,
host_mm=self.mm,
pattern_m=lhs,
pattern_mm=self.mm_ramified,
eval_context=self.eval_context,
pivot= pivot,
)
return lhs_matcher
def rewrite_rule(self, m: UUID, rhs: UUID, *, pivot:dict[Any, Any]):
yield rewrite(self.state,
rhs_m=rhs,
pattern_mm=self.mm_ramified,
lhs_match=pivot,
host_m=m,
host_mm=self.mm,
eval_context=self.eval_context,
)
def load_match(self, file: str):
with open(file, "r") as f:
return parse_and_check(self.state, f.read(), self.mm_ramified, file)

View file

@ -1,104 +0,0 @@
import importlib.util
import io
import os
from jinja2 import FileSystemLoader, Environment
from concrete_syntax.textual_od import parser as parser_od
from concrete_syntax.textual_cd import parser as parser_cd
from api.od import ODAPI
from bootstrap.scd import bootstrap_scd
from examples.schedule.generator import schedule_generator
from examples.schedule.schedule_lib import End, NullNode
from framework.conformance import Conformance, render_conformance_check_result
from state.devstate import DevState
class ScheduleActionGenerator:
def __init__(self, rule_executer, schedulefile:str):
self.rule_executer = rule_executer
self.rule_dict = {}
self.schedule: "Schedule"
self.state = DevState()
self.load_schedule(schedulefile)
def load_schedule(self, filename):
print("Loading schedule ...")
scd_mmm = bootstrap_scd(self.state)
with open("../schedule/models/scheduling_MM.od", "r") as f_MM:
mm_cs = f_MM.read()
with open(f"{filename}", "r") as f_M:
m_cs = f_M.read()
print("OK")
print("\nParsing models")
print(f"\tParsing meta model")
scheduling_mm = parser_cd.parse_cd(
self.state,
m_text=mm_cs,
)
print(f"\tParsing '{filename}_M.od' model")
scheduling_m = parser_od.parse_od(
self.state,
m_text=m_cs,
mm=scheduling_mm
)
print(f"OK")
print("\tmeta-meta-model a valid class diagram")
conf = Conformance(self.state, scd_mmm, scd_mmm)
print(render_conformance_check_result(conf.check_nominal()))
print(f"Is our '{filename}_M.od' model a valid '{filename}_MM.od' diagram?")
conf = Conformance(self.state, scheduling_m, scheduling_mm)
print(render_conformance_check_result(conf.check_nominal()))
print("OK")
od = ODAPI(self.state, scheduling_m, scheduling_mm)
g = schedule_generator(od)
output_buffer = io.StringIO()
g.generate_schedule(output_buffer)
open(f"schedule.py", "w").write(output_buffer.getvalue())
spec = importlib.util.spec_from_file_location("schedule", "schedule.py")
scedule_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(scedule_module)
self.schedule = scedule_module.Schedule(self.rule_executer)
self.load_matchers()
def load_matchers(self):
matchers = dict()
for file in self.schedule.get_matchers():
matchers[file] = self.rule_executer.load_match(file)
self.schedule.init_schedule(matchers)
def __call__(self, api: ODAPI):
exec_op = self.schedule(api)
yield from exec_op
def termination_condition(self, api: ODAPI):
if type(self.schedule.cur) == End:
return "jay"
if type(self.schedule.cur) == NullNode:
return "RRRR"
return None
def generate_dot(self):
env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
env.trim_blocks = True
env.lstrip_blocks = True
template_dot = env.get_template('schedule_dot.j2')
nodes = []
edges = []
visit = set()
self.schedule.generate_dot(nodes, edges, visit)
print("Nodes:")
print(nodes)
print("\nEdges:")
print(edges)
with open("test.dot", "w") as f_dot:
f_dot.write(template_dot.render({"nodes": nodes, "edges": edges}))

View file

@ -1,129 +0,0 @@
import sys
import os
import json
from uuid import UUID
from jinja2.runtime import Macro
from api.od import ODAPI
from jinja2 import Environment, FileSystemLoader, meta
class schedule_generator:
def __init__(self, odApi:ODAPI):
self.env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
self.env.trim_blocks = True
self.env.lstrip_blocks = True
self.template = self.env.get_template('schedule_template.j2')
self.template_wrap = self.env.get_template('schedule_template_wrap.j2')
self.api = odApi
def get_slot_value_default(item: UUID, slot:str, default):
if slot in self.api.get_slots(item):
return self.api.get_slot_value(item, slot)
return default
name_dict = lambda item: {"name": self.api.get_name(item)}
conn_dict = lambda item: {"name_from": self.api.get_name(self.api.get_source(item)),
"name_to": self.api.get_name(self.api.get_target(item)),
"gate_from": self.api.get_slot_value(item, "gate_from"),
"gate_to": self.api.get_slot_value(item, "gate_to"),
}
conn_data_event = {"Match": lambda item: False,
"Rewrite": lambda item: False,
"Data_modify": lambda item: True,
"Loop": lambda item: True,
"Print": lambda item: get_slot_value_default(item, "event", False)
}
conn_data_dict = lambda item: {"name_from": self.api.get_name(self.api.get_source(item)),
"name_to": self.api.get_name(self.api.get_target(item)),
"event": conn_data_event[self.api.get_type_name(target := self.api.get_target(item))](target)
}
rewrite_dict = lambda item: {"name": self.api.get_name(item),
"file": self.api.get_slot_value(item, "file"),
}
match_dict = lambda item: {"name": self.api.get_name(item),
"file": self.api.get_slot_value(item, "file"),
"n": self.api.get_slot_value(item, "n") \
if "n" in self.api.get_slots(item) else 'float("inf")'
}
data_modify_dict = lambda item: {"name": self.api.get_name(item),
"dict": json.loads(self.api.get_slot_value(item, "modify_dict"))
}
loop_dict = lambda item: {"name": self.api.get_name(item),
"choise": get_slot_value_default(item, "choise", False)}
print_dict = lambda item: {"name": self.api.get_name(item),
"label": get_slot_value_default(item, "label", "")}
arg_map = {"Start": name_dict, "End": name_dict,
"Match": match_dict, "Rewrite": rewrite_dict,
"Data_modify": data_modify_dict, "Loop": loop_dict,
"Exec_con": conn_dict, "Data_con": conn_data_dict,
"Print": print_dict}
self.macro_args = {tp: (macro, arg_map.get(tp)) for tp, macro in self.template.module.__dict__.items()
if type(macro) == Macro}
def _render(self, item):
type_name = self.api.get_type_name(item)
macro, arg_gen = self.macro_args[type_name]
return macro(**arg_gen(item))
def generate_schedule(self, stream = sys.stdout):
start = self.api.get_all_instances("Start")[0][1]
stack = [start]
out = {"blocks":[], "exec_conn":[], "data_conn":[], "match_files":set(), "matchers":[], "start":self.api.get_name(start)}
execBlocks = set()
exec_conn = list()
while len(stack) > 0:
exec_obj = stack.pop()
if exec_obj in execBlocks:
continue
execBlocks.add(exec_obj)
for conn in self.api.get_outgoing(exec_obj, "Exec_con"):
exec_conn.append(conn)
stack.append(self.api.get_target(conn))
stack = list(execBlocks)
data_blocks = set()
for name, p in self.api.get_all_instances("Print"):
if "event" in (event := self.api.get_slots(p)) and event:
stack.append(p)
execBlocks.add(p)
data_conn = set()
while len(stack) > 0:
obj = stack.pop()
for data_c in self.api.get_incoming(obj, "Data_con"):
data_conn.add(data_c)
source = self.api.get_source(data_c)
if not self.api.is_instance(source, "Exec") and \
source not in execBlocks and \
source not in data_blocks:
stack.append(source)
data_blocks.add(source)
for exec_item in execBlocks:
out["blocks"].append(self._render(exec_item))
if self.api.is_instance(exec_item, "Rule"):
d = self.macro_args[self.api.get_type_name(exec_item)][1](exec_item)
out["match_files"].add(d["file"])
out["matchers"].append(d)
for exec_c in exec_conn:
out["exec_conn"].append(self._render(exec_c))
for data_c in data_conn:
out["data_conn"].append(self._render(data_c))
for data_b in data_blocks:
out["blocks"].append(self._render(data_b))
print(self.template_wrap.render(out), file=stream)
# print("with open('test.dot', 'w') as f:", file=stream)
# print(f"\tf.write({self.api.get_name(start)}.generate_dot())", file=stream)

View file

@ -1,26 +0,0 @@
### association Exec_con
Integer gate_from;
Integer gate_to;
### association Data_con
### class Start [1..1]
### class End [1..*]
### class Match
optional Integer n;
### class Rewrite
### class Data_modify
String modify_dict;
### class Loop
optional Boolean choise;
## debugging tools
### class Print(In_Exec, Out_Exec, In_Data)
optional Boolean event;

View file

@ -1,46 +0,0 @@
abstract class Exec
abstract class In_Exec(Exec)
abstract class Out_Exec(Exec)
association Exec_con [0..*] Out_Exec -> In_Exec [0..*] {
Integer gate_from;
Integer gate_to;
}
abstract class Data
abstract class In_Data(Data)
abstract class Out_Data(Data)
association Data_con [0..*] Out_Data -> In_Data [0..*]
class Start [1..1] (Out_Exec)
class End [1..*] (In_Exec)
abstract class Rule (In_Exec, Out_Exec, In_Data, Out_Data)
{
String file;
}
class Match (Rule)
{
optional Integer n;
}
class Rewrite (Rule)
class Data_modify(In_Data, Out_Data)
{
String modify_dict;
}
class Loop(In_Exec, Out_Exec, In_Data, Out_Data)
{
optional Boolean choise;
}
# debugging tools
class Print(In_Exec, Out_Exec, In_Data)
{
optional Boolean event;
optional String label;
}

View file

@ -1,12 +0,0 @@
from .data_node import DataNode
from .data_modify import DataModify
from .end import End
from .exec_node import ExecNode
from .loop import Loop
from .match import Match
from .null_node import NullNode
from .print import Print
from .rewrite import Rewrite
from .start import Start
__all__ = ["DataNode", "End", "ExecNode", "Loop", "Match", "NullNode", "Rewrite", "Print", "DataModify", "Start"]

View file

@ -1,63 +0,0 @@
import functools
from typing import Any, Generator, Callable
class Data:
def __init__(self, super) -> None:
self.data: list[dict[Any, Any]] = list()
self.success: bool = False
self.super = super
@staticmethod
def store_output(func: Callable) -> Callable:
def wrapper(self, *args, **kwargs) -> Any:
output = func(self, *args, **kwargs)
self.success = output
return output
return wrapper
@store_output
def store_data(self, data_gen: Generator, n: int) -> bool:
self.data.clear()
if n == 0:
return True
i: int = 0
while (match := next(data_gen, None)) is not None:
self.data.append(match)
i+=1
if i >= n:
break
else:
if n == float("inf"):
return bool(len(self.data))
self.data.clear()
return False
return True
def get_super(self) -> int:
return self.super
def replace(self, data: "Data") -> None:
self.data.clear()
self.data.extend(data.data)
def append(self, data: Any) -> None:
self.data.append(data)
def clear(self) -> None:
self.data.clear()
def pop(self, index = -1) -> Any:
return self.data.pop(index)
def empty(self) -> bool:
return len(self.data) == 0
def __getitem__(self, index):
return self.data[index]
def __iter__(self):
return self.data.__iter__()
def __len__(self):
return self.data.__len__()

View file

@ -1,26 +0,0 @@
import functools
from typing import TYPE_CHECKING, Callable, List
from api.od import ODAPI
from examples.schedule.RuleExecuter import RuleExecuter
from .exec_node import ExecNode
from .data_node import DataNode
class DataModify(DataNode):
def __init__(self, modify_dict: dict[str,str]) -> None:
DataNode.__init__(self)
self.modify_dict: dict[str,str] = modify_dict
def input_event(self, success: bool) -> None:
if success or self.data_out.success:
self.data_out.data.clear()
for data in self.data_in.data:
self.data_out.append({self.modify_dict[key]: value for key, value in data.items() if key in self.modify_dict.keys()})
DataNode.input_event(self, success)
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=modify]")
super().generate_dot(nodes, edges, visited)

View file

@ -1,47 +0,0 @@
from typing import Any, Generator, List
from examples.schedule.schedule_lib.id_generator import IdGenerator
from .data import Data
class DataNode:
def __init__(self) -> None:
if not hasattr(self, 'id'):
self.id = IdGenerator().generate_id()
self.data_out : Data = Data(self)
self.data_in: Data | None = None
self.eventsub: list[DataNode] = list()
def connect_data(self, data_node: "DataNode", eventsub=True) -> None:
data_node.data_in = self.data_out
if eventsub:
self.eventsub.append(data_node)
def store_data(self, data_gen: Generator, n: int) -> None:
success: bool = self.data_out.store_data(data_gen, n)
for sub in self.eventsub:
sub.input_event(success)
def get_input_data(self) -> list[dict[Any, Any]]:
if not self.data_in.success:
raise Exception("Invalid input data: matching has failed")
data = self.data_in.data
if len(data) == 0:
raise Exception("Invalid input data: no data present")
return data
def input_event(self, success: bool) -> None:
self.data_out.success = success
for sub in self.eventsub:
sub.input_event(success)
def get_id(self) -> int:
return self.id
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
visited.add(self.id)
if self.data_in is not None:
edges.append(f"{self.data_in.get_super().get_id()} -> {self.get_id()} [color = green]")
self.data_in.get_super().generate_dot(nodes, edges, visited)
for sub in self.eventsub:
sub.generate_dot(nodes, edges, visited)

View file

@ -1,21 +0,0 @@
import functools
from typing import TYPE_CHECKING, List, Callable, Generator
from api.od import ODAPI
from .exec_node import ExecNode
class End(ExecNode):
def __init__(self) -> None:
super().__init__(out_connections=1)
def execute(self, od: ODAPI) -> Generator | None:
return self.terminate(od)
@staticmethod
def terminate(od: ODAPI) -> Generator:
yield f"end:", functools.partial(lambda od:(od, ""), od)
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=end]")

View file

@ -1,34 +0,0 @@
from typing import TYPE_CHECKING, List, Callable, Generator
from api.od import ODAPI
from .id_generator import IdGenerator
class ExecNode:
def __init__(self, out_connections: int = 1) -> None:
from .null_node import NullNode
self.next_state: list[ExecNode] = []
if out_connections > 0:
self.next_state = [NullNode()]*out_connections
self.id: int = IdGenerator().generate_id()
def nextState(self) -> "ExecNode":
return self.next_state[0]
def connect(self, next_state: "ExecNode", from_gate: int = 0, to_gate: int = 0) -> None:
if from_gate >= len(self.next_state):
raise IndexError
self.next_state[from_gate] = next_state
def execute(self, od: ODAPI) -> Generator | None:
return None
def get_id(self) -> int:
return self.id
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
visited.add(self.id)
for edge in self.next_state:
edges.append(f"{self.id} -> {edge.get_id()}")
for next in self.next_state:
next.generate_dot(nodes, edges, visited)

View file

@ -1,10 +0,0 @@
from typing import Callable
def generate_dot_wrap(func) -> Callable:
def wrapper(self, *args, **kwargs) -> str:
nodes = []
edges = []
self.reset_visited()
func(self, nodes, edges, *args, **kwargs)
return f"digraph G {{\n\t{"\n\t".join(nodes)}\n\t{"\n\t".join(edges)}\n}}"
return wrapper

View file

@ -1,8 +0,0 @@
from .singleton import Singleton
class IdGenerator(metaclass=Singleton):
def __init__(self):
self.id = -1
def generate_id(self) -> int:
self.id += 1
return self.id

View file

@ -1,57 +0,0 @@
import functools
from random import choice
from typing import TYPE_CHECKING, Callable, List, Generator
from api.od import ODAPI
from examples.schedule.RuleExecuter import RuleExecuter
from .exec_node import ExecNode
from .data_node import DataNode
from .data_node import Data
class Loop(ExecNode, DataNode):
def __init__(self, choice) -> None:
ExecNode.__init__(self, out_connections=2)
DataNode.__init__(self)
self.choice: bool = choice
self.cur_data: Data = Data(-1)
def nextState(self) -> ExecNode:
return self.next_state[not self.data_out.success]
def execute(self, od: ODAPI) -> Generator | None:
if self.cur_data.empty():
self.data_out.clear()
self.data_out.success = False
DataNode.input_event(self, False)
return None
if self.choice:
def select_data() -> Generator:
for i in range(len(self.cur_data)):
yield f"choice: {self.cur_data[i]}", functools.partial(self.select_next,od, i)
return select_data()
else:
self.select_next(od, -1)
return None
def input_event(self, success: bool) -> None:
if (b := self.data_out.success) or success:
self.cur_data.replace(self.data_in)
self.data_out.clear()
self.data_out.success = False
if b:
DataNode.input_event(self, False)
def select_next(self,od: ODAPI, index: int) -> tuple[ODAPI, list[str]]:
self.data_out.clear()
self.data_out.append(self.cur_data.pop(index))
DataNode.input_event(self, True)
return (od, ["data selected"])
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=Loop]")
ExecNode.generate_dot(self, nodes, edges, visited)
DataNode.generate_dot(self, nodes, edges, visited)

View file

@ -1,42 +0,0 @@
import functools
from typing import TYPE_CHECKING, Callable, List, Generator
from api.od import ODAPI
from examples.schedule.RuleExecuter import RuleExecuter
from .exec_node import ExecNode
from .data_node import DataNode
class Match(ExecNode, DataNode):
def __init__(self, label: str, n: int | float) -> None:
ExecNode.__init__(self, out_connections=2)
DataNode.__init__(self)
self.label: str = label
self.n:int = n
self.rule = None
self.rule_executer : RuleExecuter
def nextState(self) -> ExecNode:
return self.next_state[not self.data_out.success]
def execute(self, od: ODAPI) -> Generator | None:
self.match(od)
return None
def init_rule(self, rule, rule_executer):
self.rule = rule
self.rule_executer = rule_executer
def match(self, od: ODAPI) -> None:
pivot = {}
if self.data_in is not None:
pivot = self.get_input_data()[0]
print(f"matching: {self.label}\n\tpivot: {pivot}")
self.store_data(self.rule_executer.match_rule(od.m, self.rule, pivot=pivot), self.n)
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=M_{self.label.split("/")[-1]}_{self.n}]")
ExecNode.generate_dot(self, nodes, edges, visited)
DataNode.generate_dot(self, nodes, edges, visited)

View file

@ -1,25 +0,0 @@
import functools
from symtable import Function
from typing import List, Callable, Generator
from api.od import ODAPI
from .singleton import Singleton
from .exec_node import ExecNode
class NullNode(ExecNode, metaclass=Singleton):
def __init__(self):
ExecNode.__init__(self, out_connections=0)
def execute(self, od: ODAPI) -> Generator | None:
raise Exception('Null node should already have terminated the schedule')
@staticmethod
def terminate(od: ODAPI):
return None
yield # verrrry important line, dont remove this unreachable code
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=Null]")

View file

@ -1,28 +0,0 @@
import functools
from typing import TYPE_CHECKING, Callable, List, Generator
from api.od import ODAPI
from examples.schedule.RuleExecuter import RuleExecuter
from .exec_node import ExecNode
from .data_node import DataNode
class Print(ExecNode, DataNode):
def __init__(self, label: str = "") -> None:
ExecNode.__init__(self, out_connections=1)
DataNode.__init__(self)
self.label = label
def execute(self, od: ODAPI) -> Generator | None:
self.input_event(True)
return None
def input_event(self, success: bool) -> None:
print(f"{self.label}{self.data_in.data}")
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=Print_{self.label.replace(":", "")}]")
ExecNode.generate_dot(self, nodes, edges, visited)
DataNode.generate_dot(self, nodes, edges, visited)

View file

@ -1,38 +0,0 @@
import functools
from typing import List, Callable, Generator
from api.od import ODAPI
from .exec_node import ExecNode
from .data_node import DataNode
from ..RuleExecuter import RuleExecuter
class Rewrite(ExecNode, DataNode):
def __init__(self, label: str) -> None:
ExecNode.__init__(self, out_connections=1)
DataNode.__init__(self)
self.label = label
self.rule = None
self.rule_executer : RuleExecuter
def init_rule(self, rule, rule_executer):
self.rule = rule
self.rule_executer= rule_executer
def execute(self, od: ODAPI) -> Generator | None:
yield "ghello", functools.partial(self.rewrite, od)
def rewrite(self, od):
print("rewrite" + self.label)
pivot = {}
if self.data_in is not None:
pivot = self.get_input_data()[0]
self.store_data(self.rule_executer.rewrite_rule(od.m, self.rule, pivot=pivot), 1)
return ODAPI(od.state, od.m, od.mm),[f"rewrite {self.label}\n\tpivot: {pivot}\n\t{"success" if self.data_out.success else "failure"}\n"]
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=R_{self.label.split("/")[-1]}]")
ExecNode.generate_dot(self, nodes, edges, visited)
DataNode.generate_dot(self, nodes, edges, visited)

View file

@ -1,16 +0,0 @@
from typing import TYPE_CHECKING, Callable, List, Any
from .funcs import generate_dot_wrap
from .exec_node import ExecNode
class Start(ExecNode):
def __init__(self) -> None:
ExecNode.__init__(self, out_connections=1)
def generate_dot(self, nodes: List[str], edges: List[str], visited: set[int]) -> None:
if self.id in visited:
return
nodes.append(f"{self.id}[label=start]")
super().generate_dot(nodes, edges, visited)

View file

@ -1,9 +0,0 @@
digraph G {
{% for node in nodes %}
{{ node }}
{% endfor %}
{% for edge in edges %}
{{ edge }}
{% endfor %}
}

View file

@ -1,35 +0,0 @@
{% macro Start(name) %}
{{ name }} = Start()
{%- endmacro %}
{% macro End(name) %}
{{ name }} = End()
{%- endmacro %}
{% macro Match(name, file, n) %}
{{ name }} = Match("{{ file }}", {{ n }})
{%- endmacro %}
{% macro Rewrite(name, file) %}
{{ name }} = Rewrite("{{ file }}")
{%- endmacro %}
{% macro Data_modify(name, dict) %}
{{ name }} = DataModify({{ dict }})
{%- endmacro %}
{% macro Exec_con(name_from, name_to, gate_from, gate_to) %}
{{ name_from }}.connect({{ name_to }},{{ gate_from }},{{ gate_to }})
{%- endmacro %}
{% macro Data_con(name_from, name_to, event) %}
{{ name_from }}.connect_data({{ name_to }}, {{ event }})
{%- endmacro %}
{% macro Loop(name, choise) %}
{{ name }} = Loop({{ choise }})
{%- endmacro %}
{% macro Print(name, label) %}
{{ name }} = Print("{{ label }}")
{%- endmacro %}

View file

@ -1,47 +0,0 @@
from examples.schedule.schedule_lib import *
class Schedule:
def __init__(self, rule_executer):
self.start: Start
self.cur: ExecNode = None
self.rule_executer = rule_executer
def __call__(self, od):
self.cur = self.cur.nextState()
while not isinstance(self.cur, NullNode):
action_gen = self.cur.execute(od)
if action_gen is not None:
# if (action_gen := self.cur.execute(od)) is not None:
return action_gen
self.cur = self.cur.nextState()
return NullNode.terminate(od)
@staticmethod
def get_matchers():
return [
{% for file in match_files %}
"{{ file }}.od",
{% endfor %}
]
def init_schedule(self, matchers):
{% for block in blocks%}
{{ block }}
{% endfor %}
{% for conn in exec_conn%}
{{ conn }}
{% endfor %}
{% for conn_d in data_conn%}
{{ conn_d }}
{% endfor %}
self.start = {{ start }}
self.cur = {{ start }}
{% for match in matchers %}
{{ match["name"] }}.init_rule(matchers["{{ match["file"] }}.od"], self.rule_executer)
{% endfor %}
return None
def generate_dot(self, *args, **kwargs):
return self.start.generate_dot(*args, **kwargs)

View file

@ -1,2 +1,3 @@
lark==1.1.9
jinja2==3.1.4
jinja2==3.1.4
git+https://msdl.uantwerpen.be/git/jexelmans/drawio2py

View file

@ -0,0 +1,489 @@
import io
import os
import sys
import unittest
sys.path.insert(
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../"))
)
from icecream import ic
from api.od import ODAPI
from bootstrap.scd import bootstrap_scd
from examples.schedule import rule_schedular
from examples.schedule.rule_schedular import ScheduleActionGenerator
from state.devstate import DevState
from transformation.ramify import ramify
from util import loader
class Test_Meta_Model(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.dir = os.path.dirname(__file__)
state = DevState()
scd_mmm = bootstrap_scd(state)
with open(f"{cls.dir}/models/mm_petrinet.od") as file:
mm_s = file.read()
with open(f"{cls.dir}/models/m_petrinet.od") as file:
m_s = file.read()
mm = loader.parse_and_check(state, mm_s, scd_mmm, "mm")
m = loader.parse_and_check(state, m_s, mm, "m")
mm_rt_ramified = ramify(state, mm)
cls.model_param = (state, m, mm)
cls.generator_param = (state, mm, mm_rt_ramified)
def setUp(self):
self.model = ODAPI(*self.model_param)
self.out = io.StringIO()
self.generator = ScheduleActionGenerator(
*self.generator_param,
directory=self.dir + "/models",
verbose=True,
outstream=self.out,
)
def _test_conformance(
self, file: str, expected_substr_err: dict[tuple[str, str], list[list[str]]]
) -> None:
try:
self.generator.load_schedule(f"schedule/{file}")
errors = self.out.getvalue().split("\u25b8")[1:]
ic(errors)
if len(errors) != len(expected_substr_err.keys()):
ic("len total errors")
assert len(errors) == len(expected_substr_err.keys())
for err in errors:
error_lines = err.strip().split("\n")
line = error_lines[0]
for key_pattern in expected_substr_err.keys():
if (key_pattern[0] in line) and (key_pattern[1] in line):
key = key_pattern
break
else:
ic("no matching key")
ic(line)
assert False
expected = expected_substr_err[key]
if (len(error_lines) - 1) != len(expected):
ic("len substr errors")
ic(line)
assert (len(error_lines) - 1) == len(expected)
it = error_lines.__iter__()
it.__next__()
for err_line in it:
if not any(
all(exp in err_line for exp in line_exp)
for line_exp in expected
):
ic("wrong substr error")
ic(line)
ic(error_lines)
assert False
expected_substr_err.pop(key)
except AssertionError:
raise
except Exception as e:
ic(e)
assert False
def test_no_start(self):
self._test_conformance("no_start.od", {("Start", "Cardinality"): []})
def test_no_end(self):
self._test_conformance("no_end.od", {("End", "Cardinality"): []})
def test_multiple_start(self):
self._test_conformance("multiple_start.od", {("Start", "Cardinality"): []})
def test_multiple_end(self):
self._test_conformance("multiple_end.od", {("End", "Cardinality"): []})
def test_connections_start(self):
self._test_conformance(
"connections_start.od",
{
("Start", "start"): [
["input exec", "foo_in", "exist"],
["output exec", "out", "multiple"],
["output exec", "foo_out", "exist"],
["input data", "in", "exist"],
]
},
)
def test_connections_end(self):
self._test_conformance(
"connections_end.od",
{
("End", "end"): [
["input exec", "foo_in", "exist"],
["output exec", "foo_out", "exist"],
["input data", "in", "multiple"],
["input data", "out2", "exist"],
["output data", "out", "exist"],
]
},
)
def test_connections_match(self):
self._test_conformance(
"connections_match.od",
{
("Match", "m_foo"): [
["input exec", "foo_in", "exist"],
["output exec", "foo", "exist"],
["output exec", "fail", "multiple"],
["input data", "foo_in", "exist"],
["input data", "in", "multiple"],
["output data", "foo_out", "exist"],
]
},
)
def test_connections_rewrite(self):
self._test_conformance(
"connections_rewrite.od",
{
("Rewrite", "r_foo1"): [
["input exec", "foo_in", "exist"],
["output exec", "foo", "exist"],
],
("Rewrite", "r_foo2"): [
["output exec", "out", "multiple"],
["input data", "foo_in", "exist"],
["input data", "in", "multiple"],
["output data", "foo_out", "exist"],
],
},
)
def test_connections_action(self):
self._test_conformance(
"connections_action.od",
{
("Action", "a_foo1"): [
["input exec", "foo_in", "exist"],
["output exec", "out", "multiple"],
["output exec", "foo", "exist"],
["input data", "in1", "multiple"],
],
("Action", "a_foo2"): [
["input exec", "in", "exist"],
["output exec", "out3", "multiple"],
["output exec", "out", "exist"],
["input data", "in", "exist"],
["output data", "out", "exist"],
],
},
)
def test_connections_modify(self):
self._test_conformance(
"connections_modify.od",
{
("Modify", "m_foo"): [
["input exec", "in", "exist"],
["input exec", "in", "exist"],
["output exec", "out", "exist"],
["input data", "foo_in", "exist"],
["output data", "foo_out", "exist"],
["input data", "in", "multiple"],
]
},
)
def test_connections_merge(self):
self._test_conformance(
"connections_merge.od",
{
("Merge", "m_foo"): [
["input exec", "in", "exist"],
["input exec", "in", "exist"],
["output exec", "out", "exist"],
["input data", "foo_in", "exist"],
["output data", "foo_out", "exist"],
["input data", "in2", "multiple"],
]
},
)
def test_connections_store(self):
self._test_conformance(
"connections_store.od",
{
("Store", "s_foo"): [
["input exec", "foo", "exist"],
["output exec", "out", "multiple"],
["output exec", "foo", "exist"],
["input data", "foo_in", "exist"],
["output data", "foo_out", "exist"],
["input data", "2", "multiple"],
],
},
)
def test_connections_schedule(self):
self._test_conformance(
"connections_schedule.od",
{
("Schedule", "s_foo"): [
["output exec", "out", "multiple"],
["input data", "in2", "multiple"],
]
},
)
def test_connections_loop(self):
self._test_conformance(
"connections_loop.od",
{
("Loop", "l_foo"): [
["input exec", "foo_in", "exist"],
["output exec", "out", "multiple"],
["output exec", "foo", "exist"],
["input data", "foo_in", "exist"],
["output data", "foo_out", "exist"],
["input data", "in", "multiple"],
]
},
)
def test_connections_print(self):
self._test_conformance(
"connections_print.od",
{
("Print", "p_foo"): [
["input exec", "foo_in", "exist"],
["output exec", "out", "multiple"],
["output exec", "foo", "exist"],
["input data", "foo_in", "exist"],
["output data", "out", "exist"],
["input data", "in", "multiple"],
]
},
)
def test_fields_start(self):
self._test_conformance(
"fields_start.od",
{
("Start", "Cardinality"): [],
("Start", "string"): [
["Unexpected type", "ports_exec_out", "str"],
["Unexpected type", "ports_data_out", "str"],
],
("Start", '"int"'): [
["Unexpected type", "ports_exec_out", "int"],
["Unexpected type", "ports_data_out", "int"],
],
("Start", "tuple"): [
["Unexpected type", "ports_exec_out", "tuple"],
["Unexpected type", "ports_data_out", "tuple"],
],
("Start", "dict"): [
["Unexpected type", "ports_exec_out", "dict"],
["Unexpected type", "ports_data_out", "dict"],
],
("Start", "none"): [
["Unexpected type", "ports_exec_out", "NoneType"],
["Unexpected type", "ports_data_out", "NoneType"],
],
("Start", "invalid"): [
["Invalid python", "ports_exec_out"],
["Invalid python", "ports_data_out"],
],
("Start", "subtype"): [
["Unexpected type", "ports_exec_out", "list"],
["Unexpected type", "ports_data_out", "list"],
],
("Start", "code"): [
["Unexpected type", "ports_exec_out"],
["Unexpected type", "ports_data_out"],
],
},
)
def test_fields_end(self):
self._test_conformance(
"fields_end.od",
{
("End", "Cardinality"): [],
("End", "string"): [
["Unexpected type", "ports_exec_in", "str"],
["Unexpected type", "ports_data_in", "str"],
],
("End", '"int"'): [
["Unexpected type", "ports_exec_in", "int"],
["Unexpected type", "ports_data_in", "int"],
],
("End", "tuple"): [
["Unexpected type", "ports_exec_in", "tuple"],
["Unexpected type", "ports_data_in", "tuple"],
],
("End", "dict"): [
["Unexpected type", "ports_exec_in", "dict"],
["Unexpected type", "ports_data_in", "dict"],
],
("End", "none"): [
["Unexpected type", "ports_exec_in", "NoneType"],
["Unexpected type", "ports_data_in", "NoneType"],
],
("End", "invalid"): [
["Invalid python", "ports_exec_in"],
["Invalid python", "ports_data_in"],
],
("End", "subtype"): [
["Unexpected type", "ports_exec_in", "list"],
["Unexpected type", "ports_data_in", "list"],
],
("End", "code"): [
["Unexpected type", "ports_exec_in"],
["Unexpected type", "ports_data_in"],
],
},
)
def test_fields_action(self):
self._test_conformance(
"fields_action.od",
{
("cardinality", "Action_action"): [],
("Action", "string"): [
["Unexpected type", "ports_exec_out", "str"],
["Unexpected type", "ports_exec_in", "str"],
["Unexpected type", "ports_data_out", "str"],
["Unexpected type", "ports_data_in", "str"],
],
("Action", '"int"'): [
["Unexpected type", "ports_exec_out", "int"],
["Unexpected type", "ports_exec_in", "int"],
["Unexpected type", "ports_data_out", "int"],
["Unexpected type", "ports_data_in", "int"],
],
("Action", "tuple"): [
["Unexpected type", "ports_exec_out", "tuple"],
["Unexpected type", "ports_exec_in", "tuple"],
["Unexpected type", "ports_data_out", "tuple"],
["Unexpected type", "ports_data_in", "tuple"],
],
("Action", "dict"): [
["Unexpected type", "ports_exec_out", "dict"],
["Unexpected type", "ports_exec_in", "dict"],
["Unexpected type", "ports_data_out", "dict"],
["Unexpected type", "ports_data_in", "dict"],
],
("Action", "none"): [
["Unexpected type", "ports_exec_out", "NoneType"],
["Unexpected type", "ports_exec_in", "NoneType"],
["Unexpected type", "ports_data_out", "NoneType"],
["Unexpected type", "ports_data_in", "NoneType"],
],
("Action", '"invalid"'): [
["Invalid python", "ports_exec_out"],
["Invalid python", "ports_exec_in"],
["Invalid python", "ports_data_out"],
["Invalid python", "ports_data_in"],
],
("Action_action", "invalid_action"): [],
("Action", "subtype"): [
["Unexpected type", "ports_exec_out", "list"],
["Unexpected type", "ports_exec_in", "list"],
["Unexpected type", "ports_data_out", "list"],
["Unexpected type", "ports_data_in", "list"],
],
("Action", "code"): [
["Unexpected type", "ports_exec_out"],
["Unexpected type", "ports_exec_in"],
["Unexpected type", "ports_data_out"],
["Unexpected type", "ports_data_in"],
],
},
)
def test_fields_modify(self):
self._test_conformance(
"fields_modify.od",
{
("Modify", "string"): [
["Unexpected type", "rename", "str"],
["Unexpected type", "delete", "str"],
],
("Modify", "list"): [["Unexpected type", "rename", "list"]],
("Modify", "set"): [["Unexpected type", "rename", "set"]],
("Modify", "tuple"): [
["Unexpected type", "rename", "tuple"],
["Unexpected type", "delete", "tuple"],
],
("Modify", "dict"): [["Unexpected type", "delete", "dict"]],
("Modify", "none"): [
["Unexpected type", "rename", "NoneType"],
["Unexpected type", "delete", "NoneType"],
],
("Modify", "invalid"): [
["Invalid python", "rename"],
["Invalid python", "delete"],
],
("Modify", "subtype"): [
["Unexpected type", "rename", "dict"],
["Unexpected type", "delete", "list"],
],
("Modify", "code"): [
["Unexpected type", "rename"],
["Unexpected type", "delete"],
],
("Modify", "joined"): [["rename", "delete", "disjoint"]],
},
)
def test_fields_merge(self):
self._test_conformance(
"fields_merge.od",
{
("cardinality", "Merge_ports_data_in"): [],
("Merge", "string"): [["Unexpected type", "ports_data_in", "str"]],
("Merge", "tuple"): [["Unexpected type", "ports_data_in", "tuple"]],
("Merge", "dict"): [["Unexpected type", "ports_data_in", "dict"]],
("Merge", "none"): [["Unexpected type", "ports_data_in", "NoneType"]],
("Merge", "invalid"): [["Invalid python", "ports_data_in"]],
("Merge", "subtype"): [["Unexpected type", "ports_data_in", "list"]],
("Merge", "code"): [["Unexpected type", "ports_data_in"]],
("Merge", "no"): [["Missing", "slot", "ports_data_in"]],
},
)
def test_fields_store(self):
self._test_conformance(
"fields_store.od",
{
("cardinality", "Store_ports"): [],
("Store", "string"): [["Unexpected type", "ports", "str"]],
("Store", "tuple"): [["Unexpected type", "ports", "tuple"]],
("Store", "dict"): [["Unexpected type", "ports", "dict"]],
("Store", "none"): [["Unexpected type", "ports", "NoneType"]],
("Store", "invalid"): [["Invalid python", "ports"]],
("Store", "subtype"): [["Unexpected type", "ports", "list"]],
("Store", "code"): [["Unexpected type", "ports"]],
("Store", "no"): [["Missing", "slot", "ports"]],
},
)
def test_fields_print(self):
self._test_conformance(
"fields_print.od",
{
("Print_custom", "list_custom"): [["Unexpected type", "custom", "list"]],
("Print_custom", "set_custom"): [["Unexpected type", "custom", "set"]],
("Print_custom", "tuple_custom"): [["Unexpected type", "custom", "tuple"]],
("Print_custom", "dict_custom"): [["Unexpected type", "custom", "dict"]],
("Print_custom", "none_custom"): [["Unexpected type", "custom", "NoneType"]],
("Print_custom", "invalid_custom"): [["Invalid python", "custom"]],
("Print_custom", "subtype_custom"): [["Unexpected type", "custom", "list"]],
("Print_custom", "code_custom"): [["Unexpected type", "custom"]],
},
)
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1,45 @@
import io
import os
import unittest
from transformation.schedule import rule_scheduler
from transformation.schedule.rule_scheduler import RuleSchedular
from state.devstate import DevState
class MyTestCase(unittest.TestCase):
def setUp(self):
state = DevState()
self.generator = RuleSchedular(state, "", "")
def test_empty(self):
try:
self.generator.generate_schedule(
f"{os.path.dirname(__file__)}/drawio/Empty.drawio"
)
# buffer = io.BytesIO()
# self.generator.generate_dot(buffer)
except Exception as e:
assert False
def test_simple(self):
try:
self.generator.generate_schedule(
f"{os.path.dirname(__file__)}/drawio/StartToEnd.drawio"
)
# buffer = io.BytesIO()
# self.generator.generate_dot(buffer)
except Exception as e:
assert False
# def test_unsupported(self):
# try:
# self.generator.generate_schedule("Tests/drawio/Unsupported.drawio")
# # buffer = io.BytesIO()
# # self.generator.generate_dot(buffer)
# except Exception as e:
# assert(False)
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1 @@
<mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/></root></mxGraphModel>

View file

@ -0,0 +1,24 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" version="26.2.14">
<diagram id="EvjeMC12HsgBk4t1Z8cF" name="Page-1">
<mxGraphModel dx="949" dy="540" 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" />
<mxCell id="ym0EkMZWyknAE99nMXu0-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="ym0EkMZWyknAE99nMXu0-7" target="ym0EkMZWyknAE99nMXu0-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ym0EkMZWyknAE99nMXu0-10" value="out -&amp;gt; in" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ym0EkMZWyknAE99nMXu0-9">
<mxGeometry x="0.1167" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ym0EkMZWyknAE99nMXu0-7" value="Start" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="330" y="310" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="ym0EkMZWyknAE99nMXu0-8" value="End" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="560" y="310" width="110" height="50" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View file

@ -0,0 +1,75 @@
<mxfile>
<diagram id="prtHgNgQTEPvFCAcTncT" name="Page-1">
<mxGraphModel dx="1223" dy="645" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="dNxyNK7c78bLwvsdeMH5-19" value="Pool" style="swimlane;html=1;childLayout=stackLayout;resizeParent=1;resizeParentMax=0;horizontal=0;startSize=20;horizontalStack=0;" parent="1" vertex="1">
<mxGeometry x="120" y="120" width="450" height="360" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-27" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;endArrow=none;endFill=0;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-24" target="dNxyNK7c78bLwvsdeMH5-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-28" target="dNxyNK7c78bLwvsdeMH5-30" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-28" target="dNxyNK7c78bLwvsdeMH5-34" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-26" target="dNxyNK7c78bLwvsdeMH5-36" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="180" y="340" />
<mxPoint x="400" y="340" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-20" value="Lane 1" style="swimlane;html=1;startSize=20;horizontal=0;" parent="dNxyNK7c78bLwvsdeMH5-19" vertex="1">
<mxGeometry x="20" width="430" height="120" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="dNxyNK7c78bLwvsdeMH5-20" source="dNxyNK7c78bLwvsdeMH5-23" target="dNxyNK7c78bLwvsdeMH5-24" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-23" value="" style="ellipse;whiteSpace=wrap;html=1;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1">
<mxGeometry x="40" y="40" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-24" value="" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1">
<mxGeometry x="120" y="30" width="80" height="60" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-33" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-20" source="dNxyNK7c78bLwvsdeMH5-30" target="dNxyNK7c78bLwvsdeMH5-32" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-30" value="" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1">
<mxGeometry x="240" y="30" width="80" height="60" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-32" value="" style="ellipse;whiteSpace=wrap;html=1;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1">
<mxGeometry x="360" y="40" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-21" value="Lane 2" style="swimlane;html=1;startSize=20;horizontal=0;" parent="dNxyNK7c78bLwvsdeMH5-19" vertex="1">
<mxGeometry x="20" y="120" width="430" height="120" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-21" source="dNxyNK7c78bLwvsdeMH5-26" target="dNxyNK7c78bLwvsdeMH5-28" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-26" value="" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-21" vertex="1">
<mxGeometry x="120" y="30" width="80" height="60" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-28" value="" style="rhombus;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-21" vertex="1">
<mxGeometry x="260" y="40" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-22" value="Lane 3" style="swimlane;html=1;startSize=20;horizontal=0;" parent="dNxyNK7c78bLwvsdeMH5-19" vertex="1">
<mxGeometry x="20" y="240" width="430" height="120" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-22" source="dNxyNK7c78bLwvsdeMH5-34" target="dNxyNK7c78bLwvsdeMH5-36" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-34" value="" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-22" vertex="1">
<mxGeometry x="240" y="20" width="80" height="60" as="geometry" />
</mxCell>
<mxCell id="dNxyNK7c78bLwvsdeMH5-36" value="" style="rhombus;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-22" vertex="1">
<mxGeometry x="360" y="30" width="40" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View file

@ -0,0 +1,22 @@
p0:PNPlace
p1:PNPlace
t0:PNTransition
:arc (p0 -> t0)
:arc (t0 -> p1)
t1:PNTransition
:arc (p1 -> t1)
:arc (t1 -> p0)
p0s:PNPlaceState {
numTokens = 1;
}
:pn_of (p0s -> p0)
p1s:PNPlaceState {
numTokens = 0;
}
:pn_of (p1s -> p1)

View file

@ -0,0 +1,31 @@
# Places, transitions, arcs (and only one kind of arc)
PNConnectable:Class { abstract = True; }
arc:Association (PNConnectable -> PNConnectable)
PNPlace:Class
PNTransition:Class
# inhibitor arc
inh_arc:Association (PNPlace -> PNTransition)
:Inheritance (PNPlace -> PNConnectable)
:Inheritance (PNTransition -> PNConnectable)
# A place has a number of tokens, and that's it.
PNPlaceState:Class
PNPlaceState_numTokens:AttributeLink (PNPlaceState -> Integer) {
name = "numTokens";
optional = False;
constraint = `"numTokens cannot be negative" if get_value(get_target(this)) < 0 else None`;
}
pn_of:Association (PNPlaceState -> PNPlace) {
# one-to-one
source_lower_cardinality = 1;
source_upper_cardinality = 1;
target_lower_cardinality = 1;
target_upper_cardinality = 1;
}

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,62 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
a_void:Action{
ports_data_in = `["in1", "in2"]`;
ports_data_out = `["out1", "out2"]`;
action=`print("hello foo1")`;
}
a_foo1:Action{
ports_data_in = `["in1", "in2"]`;
ports_data_out = `["out1", "out2"]`;
action=`print("hello foo1")`;
}
a_foo2:Action{
ports_exec_in = `["in2"]`;
ports_exec_out = `["out2", "out3"]`;
action=`print("hello foo2")`;
}
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> a_foo1) {from="success";to="in";}
:Conn_exec (m2 -> a_foo1) {from="fail";to="in";}
:Conn_exec (m3 -> a_foo1) {from="success";to="foo_in";}
:Conn_exec (m3 -> a_foo2) {from="fail";to="in2";}
:Conn_exec (a_foo1 -> a_foo2) {from="out";to="in";}
:Conn_exec (a_foo1 -> a_foo2) {from="out";to="in2";}
:Conn_exec (a_foo1 -> a_foo2) {from="foo";to="in2";}
:Conn_exec (a_foo2 -> end) {from="out";to="in";}
:Conn_exec (a_foo2 -> end) {from="out2";to="in";}
:Conn_exec (a_foo2 -> end) {from="out3";to="in";}
:Conn_exec (a_foo2 -> end) {from="out3";to="in";}
:Conn_data (start -> a_foo2) {from="1";to="in";}
:Conn_data (a_foo2-> m2) {from="out";to="in";}
:Conn_data (start -> a_foo1) {from="1";to="in1";}
:Conn_data (start -> a_foo1) {from="2";to="in1";}
:Conn_data (start -> a_foo1) {from="3";to="in2";}
:Conn_data (a_foo1 -> end) {from="out1";to="1";}
:Conn_data (a_foo1 -> end) {from="out1";to="2";}
:Conn_data (a_foo1 -> end) {from="out2";to="3";}

View file

@ -0,0 +1,31 @@
start:Start
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
end:End {
ports_exec_in = `["out", "in"]`;
ports_data_in = `["out", "in"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> end) {from="success";to="in";}
:Conn_exec (m2 -> end) {from="fail";to="out";}
:Conn_exec (m3 -> end) {from="success";to="out";}
:Conn_exec (m3 -> end) {from="fail";to="foo_in";}
:Conn_exec (end -> m) {from="foo_out";to="in";}
:Conn_data (m -> end) {from="out";to="in";}
:Conn_data (m2 -> end) {from="out";to="in";}
:Conn_data (m3 -> end) {from="out";to="out";}
:Conn_data (m3 -> end) {from="out";to="out2";}
:Conn_data (end -> m) {from="out";to="in";}

View file

@ -0,0 +1,44 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
l:Loop
l_foo:Loop
l_void:Loop
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> l_foo) {from="success";to="in";}
:Conn_exec (m2 -> l_foo) {from="fail";to="in";}
:Conn_exec (m3 -> l_foo) {from="success";to="foo_in";}
:Conn_exec (l_foo -> l_foo) {from="out";to="in";}
:Conn_exec (l_foo -> end) {from="out";to="in";}
:Conn_exec (l_foo -> end) {from="it";to="in";}
:Conn_exec (l_foo -> end) {from="foo";to="in";}
:Conn_data (start -> l) {from="1";to="in";}
:Conn_data (l -> m2) {from="out";to="in";}
:Conn_data (start -> l_foo) {from="1";to="in";}
:Conn_data (start -> l_foo) {from="2";to="in";}
:Conn_data (start -> l_foo) {from="3";to="foo_in";}
:Conn_data (l_foo -> end) {from="out";to="1";}
:Conn_data (l_foo -> end) {from="out";to="2";}
:Conn_data (l_foo -> end) {from="foo_out";to="3";}

View file

@ -0,0 +1,49 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
m_foo:Match{
file="rules/transition.od";
}
m_void:Match{
file="rules/transition.od";
}
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> m_foo) {from="success";to="in";}
:Conn_exec (m2 -> m_foo) {from="fail";to="in";}
:Conn_exec (m3 -> m_foo) {from="success";to="foo_in";}
:Conn_exec (m3 -> m_foo) {from="fail";to="in";}
:Conn_exec (m_foo -> end) {from="fail";to="in";}
:Conn_exec (m_foo -> end) {from="success";to="in";}
:Conn_exec (m_foo -> end) {from="fail";to="in";}
:Conn_exec (m_foo -> end) {from="foo";to="in";}
:Conn_data (start -> m) {from="1";to="in";}
:Conn_data (m -> m2) {from="out";to="in";}
:Conn_data (start -> m_foo) {from="1";to="in";}
:Conn_data (start -> m_foo) {from="2";to="in";}
:Conn_data (start -> m_foo) {from="3";to="foo_in";}
:Conn_data (m_foo -> end) {from="out";to="1";}
:Conn_data (m_foo -> end) {from="out";to="2";}
:Conn_data (m_foo -> end) {from="foo_out";to="3";}

View file

@ -0,0 +1,42 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
m_foo:Merge {
ports_data_in = `["in1", "in2"]`;
}
m_void:Merge {
ports_data_in = `["in1", "in2"]`;
}
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> m_foo) {from="success";to="in";}
:Conn_exec (m2 -> m_foo) {from="fail";to="in";}
:Conn_exec (m_foo -> end) {from="out";to="in";}
:Conn_data (start -> m_foo) {from="1";to="in1";}
:Conn_data (start -> m_foo) {from="1";to="in2";}
:Conn_data (start -> m_foo) {from="2";to="in2";}
:Conn_data (start -> m_foo) {from="3";to="foo_in";}
:Conn_data (m_foo -> end) {from="out";to="1";}
:Conn_data (m_foo -> end) {from="out";to="2";}
:Conn_data (m_foo -> end) {from="foo_out";to="3";}

View file

@ -0,0 +1,41 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
m_foo:Modify
m_void:Modify
mo:Modify
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> m_foo) {from="success";to="in";}
:Conn_exec (m2 -> m_foo) {from="fail";to="in";}
:Conn_exec (m_foo -> end) {from="out";to="in";}
:Conn_data (start -> mo) {from="1";to="in";}
:Conn_data (mo -> m2) {from="out";to="in";}
:Conn_data (start -> m_foo) {from="1";to="in";}
:Conn_data (start -> m_foo) {from="2";to="in";}
:Conn_data (start -> m_foo) {from="3";to="foo_in";}
:Conn_data (m_foo -> end) {from="out";to="1";}
:Conn_data (m_foo -> end) {from="out";to="2";}
:Conn_data (m_foo -> end) {from="foo_out";to="3";}

View file

@ -0,0 +1,41 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
p_foo:Print
p_void:Print
p:Print
end:End
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> p_foo) {from="success";to="in";}
:Conn_exec (m2 -> p_foo) {from="fail";to="in";}
:Conn_exec (m3 -> p_foo) {from="success";to="foo_in";}
:Conn_exec (m3 -> p) {from="fail";to="in";}
:Conn_exec (p -> end) {from="out";to="in";}
:Conn_exec (p_foo -> p_foo) {from="out";to="in";}
:Conn_exec (p_foo -> end) {from="out";to="in";}
:Conn_exec (p_foo -> end) {from="foo";to="in";}
:Conn_data (start -> p) {from="1";to="in";}
:Conn_data (start -> p_foo) {from="1";to="in";}
:Conn_data (start -> p_foo) {from="2";to="in";}
:Conn_data (start -> p_foo) {from="3";to="foo_in";}
:Conn_data (p_foo -> m2) {from="out";to="in";}

View file

@ -0,0 +1,52 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
r_foo1:Rewrite{
file="rules/transition.od";
}
r_foo2:Rewrite{
file="rules/transition.od";
}
r_void:Rewrite{
file="rules/transition.od";
}
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> r_foo1) {from="success";to="in";}
:Conn_exec (m2 -> r_foo1) {from="fail";to="in";}
:Conn_exec (m3 -> r_foo1) {from="success";to="foo_in";}
:Conn_exec (m3 -> r_foo1) {from="fail";to="in";}
:Conn_exec (r_foo1 -> r_foo2) {from="out";to="in";}
:Conn_exec (r_foo1 -> end) {from="foo";to="in";}
:Conn_exec (r_foo2 -> end) {from="out";to="in";}
:Conn_exec (r_foo2 -> end) {from="out";to="in";}
:Conn_data (start -> r_foo1) {from="1";to="in";}
:Conn_data (r_foo1-> m2) {from="out";to="in";}
:Conn_data (start -> r_foo2) {from="1";to="in";}
:Conn_data (start -> r_foo2) {from="2";to="in";}
:Conn_data (start -> r_foo2) {from="3";to="foo_in";}
:Conn_data (r_foo2 -> end) {from="out";to="1";}
:Conn_data (r_foo2 -> end) {from="out";to="2";}
:Conn_data (r_foo2 -> end) {from="foo_out";to="3";}

View file

@ -0,0 +1,50 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
s_foo:Schedule{
file="hello.od";
}
s_void:Schedule{
file="hello.od";
}
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> s_foo) {from="success";to="in";}
:Conn_exec (m2 -> s_foo) {from="fail";to="in";}
:Conn_exec (m3 -> s_foo) {from="success";to="foo";}
:Conn_exec (m3 -> s_foo) {from="fail";to="foo2";}
:Conn_exec (s_foo -> s_foo) {from="out";to="in";}
:Conn_exec (s_foo -> s_foo) {from="out";to="in2";}
:Conn_exec (s_foo -> s_foo) {from="foo";to="foo3";}
:Conn_exec (s_foo -> end) {from="out4";to="in";}
:Conn_exec (s_foo -> end) {from="out2";to="in";}
:Conn_exec (s_foo -> end) {from="out5";to="in";}
:Conn_exec (s_foo -> end) {from="out3";to="in";}
:Conn_data (start -> s_foo) {from="1";to="in1";}
:Conn_data (start -> s_foo) {from="1";to="in2";}
:Conn_data (start -> s_foo) {from="2";to="in2";}
:Conn_data (start -> s_foo) {from="3";to="foo_in";}
:Conn_data (s_foo -> end) {from="out";to="1";}
:Conn_data (s_foo -> end) {from="out";to="2";}
:Conn_data (s_foo -> end) {from="foo_out";to="3";}

View file

@ -0,0 +1,27 @@
start:Start {
ports_exec_out = `["out", "in"]`;
ports_data_out = `["out", "in"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
end:End
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (start -> m) {from="in";to="in";}
:Conn_exec (start -> m) {from="foo_out";to="in";}
:Conn_exec (m -> start) {from="fail";to="foo_in";}
:Conn_exec (m -> end) {from="success";to="in";}
:Conn_data (start -> m) {from="out";to="in";}
:Conn_data (start -> m2) {from="out";to="in";}
:Conn_data (start -> m3) {from="in";to="in";}
:Conn_data (m -> start) {from="out";to="in";}

View file

@ -0,0 +1,47 @@
start:Start {
ports_data_out = `["1", "2", "3"]`;
}
m:Match{
file="rules/transition.od";
}
m2:Match{
file="rules/transition.od";
}
m3:Match{
file="rules/transition.od";
}
s_foo:Store {
ports = `["1", "2", "3"]`;
}
s_void:Store {
ports = `["1", "2", "3"]`;
}
end:End {
ports_data_in = `["1", "2", "3"]`;
}
:Conn_exec (start -> m) {from="out";to="in";}
:Conn_exec (m -> m2) {from="fail";to="in";}
:Conn_exec (m -> m3) {from="success";to="in";}
:Conn_exec (m2 -> s_foo) {from="success";to="in";}
:Conn_exec (m2 -> s_foo) {from="fail";to="in";}
:Conn_exec (m3 -> s_foo) {from="success";to="1";}
:Conn_exec (m3 -> s_foo) {from="fail";to="foo";}
:Conn_exec (s_foo -> end) {from="out";to="in";}
:Conn_exec (s_foo -> s_foo) {from="1";to="2";}
:Conn_exec (s_foo -> end) {from="out";to="in";}
:Conn_exec (s_foo -> s_foo) {from="foo";to="2";}
:Conn_data (start -> s_foo) {from="1";to="1";}
:Conn_data (start -> s_foo) {from="1";to="2";}
:Conn_data (start -> s_foo) {from="2";to="2";}
:Conn_data (start -> s_foo) {from="3";to="foo_in";}
:Conn_data (s_foo -> end) {from="out";to="1";}
:Conn_data (s_foo -> end) {from="out";to="2";}
:Conn_data (s_foo -> end) {from="foo_out";to="3";}

View file

@ -0,0 +1,83 @@
string:Action {
ports_exec_in = `'["out", "in"]'`;
ports_exec_out = `'["out", "in"]'`;
ports_data_in = `'["out", "in"]'`;
ports_data_out = `'["out", "in"]'`;
action = `'["out", "in"]'`;
}
int:Action {
ports_exec_in = `123`;
ports_exec_out = `123`;
ports_data_in = `123`;
ports_data_out = `123`;
action = `123`;
}
list:Action {
ports_exec_out = `["out", "in"]`;
ports_exec_in = `["out", "in"]`;
ports_data_out = `["out", "in"]`;
ports_data_in = `["out", "in"]`;
action = `["out", "in"]`;
}
set:Action {
ports_exec_in = `{"out", "in"}`;
ports_exec_out = `{"out", "in"}`;
ports_data_in = `{"out", "in"}`;
ports_data_out = `{"out", "in"}`;
action = `{"out", "in"}`;
}
tuple:Action {
ports_exec_in = `("out", "in")`;
ports_exec_out = `("out", "in")`;
ports_data_in = `("out", "in")`;
ports_data_out = `("out", "in")`;
action = `("out", "in")`;
}
dict:Action {
ports_exec_in = `{"out": "in"}`;
ports_exec_out = `{"out": "in"}`;
ports_data_in = `{"out": "in"}`;
ports_data_out = `{"out": "in"}`;
action = `{"out": "in"}`;
}
none:Action {
ports_exec_in = `None`;
ports_exec_out = `None`;
ports_data_in = `None`;
ports_data_out = `None`;
action = `None`;
}
invalid:Action {
ports_exec_in = `[{a(0)['qkja("fyvka`;
ports_exec_out = `[{a(0)['qkja("fyvka`;
ports_data_in = `["", [{]]`;
ports_data_out = `["", [{]]`;
action = `hu(ja&{]8}]`;
}
subtype:Action {
ports_exec_in = `[1, 2]`;
ports_exec_out = `[1, 2]`;
ports_data_in = `[1, 2]`;
ports_data_out = `[1, 2]`;
action = `[1, 2]`;
}
code:Action {
ports_exec_in = `print("hello world")`;
ports_exec_out = `print("hello world")`;
ports_data_in = `print("hello world")`;
ports_data_out = `print("hello world")`;
action = `print("hello world")`;
}
no:Action
start:Start
end:End

View file

@ -0,0 +1,52 @@
start:Start
string:End {
ports_exec_in = `'["out", "in"]'`;
ports_data_in = `'["out", "in"]'`;
}
int:End {
ports_exec_in = `123`;
ports_data_in = `123`;
}
list:End {
ports_exec_in = `["out", "in"]`;
ports_data_in = `["out", "in"]`;
}
set:End {
ports_exec_in = `{"out", "in"}`;
ports_data_in = `{"out", "in"}`;
}
tuple:End {
ports_exec_in = `("out", "in")`;
ports_data_in = `("out", "in")`;
}
dict:End {
ports_exec_in = `{"out": "in"}`;
ports_data_in = `{"out": "in"}`;
}
none:End {
ports_exec_in = `None`;
ports_data_in = `None`;
}
invalid:End {
ports_exec_in = `[{a(0)['qkja("fyvka`;
ports_data_in = `["", [{]]`;
}
subtype:End {
ports_exec_in = `[1, 2]`;
ports_data_in = `[1, 2]`;
}
code:End {
ports_exec_in = `print("hello world")`;
ports_data_in = `print("hello world")`;
}
no:End

View file

@ -0,0 +1,39 @@
string:Merge {
ports_data_in = `'["out", "in"]'`;
}
list:Merge {
ports_data_in = `["out", "in"]`;
}
set:Merge {
ports_data_in = `{"out", "in"}`;
}
tuple:Merge {
ports_data_in = `("out", "in")`;
}
dict:Merge {
ports_data_in = `{"out": "in"}`;
}
none:Merge {
ports_data_in = `None`;
}
invalid:Merge {
ports_data_in = `["", [{]]`;
}
subtype:Merge {
ports_data_in = `[1, 2]`;
}
code:Merge {
ports_data_in = `print("hello world")`;
}
no:Merge
start:Start
end:End

View file

@ -0,0 +1,51 @@
string:Modify {
rename = `'["out", "in"]'`;
delete = `'["out", "in"]'`;
}
list:Modify {
rename = `["out", "in"]`;
delete = `["out", "in"]`;
}
set:Modify {
rename = `{"out", "in"}`;
delete = `{"out", "in"}`;
}
tuple:Modify {
rename = `("out", "in")`;
delete = `("out", "in")`;
}
dict:Modify {
rename = `{"out": "in"}`;
delete = `{"out": "in"}`;
}
none:Modify {
rename = `None`;
delete = `None`;
}
invalid:Modify {
rename = `[{a(0)['qkja("fyvka`;
delete = `["", [{]]`;
}
subtype:Modify {
rename = `{1: 2}`;
delete = `[1, 2]`;
}
code:Modify {
rename = `print("hello world")`;
delete = `print("hello world")`;
}
joined:Modify {
rename = `{"a":"1", "b":"2", "c":"3"}`;
delete = `{"a", "d"}`;
}
start:Start
end:End

View file

@ -0,0 +1,39 @@
string:Print {
custom = `'["port_out", "port_in"]'`;
}
list:Print {
custom = `["port_out", "port_in"]`;
}
set:Print {
custom = `{"port_out", "port_in"}`;
}
tuple:Print {
custom = `("port_out", "port_in")`;
}
dict:Print {
custom = `{"port_out": "port_in"}`;
}
none:Print {
custom = `None`;
}
invalid:Print {
custom = `["", [{]]`;
}
subtype:Print {
custom = `[1, 2]`;
}
code:Print {
custom = `print("hello world")`;
}
no:Print
start:Start
end:End

View file

@ -0,0 +1,52 @@
string:Start {
ports_exec_out = `'["out", "in"]'`;
ports_data_out = `'["out", "in"]'`;
}
int:Start {
ports_exec_out = `123`;
ports_data_out = `123`;
}
list:Start {
ports_exec_out = `["out", "in"]`;
ports_data_out = `["out", "in"]`;
}
set:Start {
ports_exec_out = `{"out", "in"}`;
ports_data_out = `{"out", "in"}`;
}
tuple:Start {
ports_exec_out = `("out", "in")`;
ports_data_out = `("out", "in")`;
}
dict:Start {
ports_exec_out = `{"out": "in"}`;
ports_data_out = `{"out": "in"}`;
}
none:Start {
ports_exec_out = `None`;
ports_data_out = `None`;
}
invalid:Start {
ports_exec_out = `[{a(0)['qkja("fyvka`;
ports_data_out = `["", [{]]`;
}
subtype:Start {
ports_exec_out = `[1, 2]`;
ports_data_out = `[1, 2]`;
}
code:Start {
ports_exec_out = `print("hello world")`;
ports_data_out = `print("hello world")`;
}
no:Start
end:End

View file

@ -0,0 +1,39 @@
string:Store {
ports = `'["port_out", "port_in"]'`;
}
list:Store {
ports = `["port_out", "port_in"]`;
}
set:Store {
ports = `{"port_out", "port_in"}`;
}
tuple:Store {
ports = `("port_out", "port_in")`;
}
dict:Store {
ports = `{"port_out": "port_in"}`;
}
none:Store {
ports = `None`;
}
invalid:Store {
ports = `["", [{]]`;
}
subtype:Store {
ports = `[1, 2]`;
}
code:Store {
ports = `print("hello world")`;
}
no:Store
start:Start
end:End

View file

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

View file

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

View file

@ -0,0 +1 @@
start:Start

View file

@ -0,0 +1 @@
end:End

View file

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

View file

View file

@ -0,0 +1,197 @@
import sys
import os
from uuid import UUID
from black.trans import Callable
from jinja2.runtime import Macro
from api.od import ODAPI
from jinja2 import Environment, FileSystemLoader
class schedule_generator:
def __init__(self, odApi: ODAPI):
self.env = Environment(
loader=FileSystemLoader(
os.path.join(os.path.dirname(__file__), "templates")
)
)
self.env.trim_blocks = True
self.env.lstrip_blocks = True
self.template = self.env.get_template("schedule_template.j2")
self.template_wrap = self.env.get_template("schedule_template_wrap.j2")
self.api = odApi
def _get_slot_value_default(item: UUID, slot: str, default):
if slot in self.api.get_slots(item):
return self.api.get_slot_value(item, slot)
return default
conn_data_event = {
"Match": lambda item: False,
"Rewrite": lambda item: False,
"Modify": lambda item: True,
"Merge": lambda item: True,
"Loop": lambda item: True,
"Action": lambda item: _get_slot_value_default(item, "event", False),
"Print": lambda item: _get_slot_value_default(item, "event", False),
"Store": lambda item: False,
"Schedule": lambda item: False,
"End": lambda item: False,
}
arg_map = {
"Loop": (name_dict := lambda item: {"name": self.api.get_name(item)}),
"Start": lambda item: {
**name_dict(item),
"ports_exec_out": eval(
self.api.get_slot_value_default(item, "ports_exec_out", "['out']")
),
"ports_data_out": eval(
self.api.get_slot_value_default(item, "ports_data_out", "[]")
),
},
"End": lambda item: {
**name_dict(item),
"ports_exec_in": eval(
self.api.get_slot_value_default(item, "ports_exec_in", "['in']")
),
"ports_data_in": eval(
self.api.get_slot_value_default(item, "ports_data_in", "[]")
),
},
"Rewrite": (
file_dict := lambda item: {
**name_dict(item),
"file": self.api.get_slot_value(item, "file"),
}
),
"Match": lambda item: {
**file_dict(item),
"n": self.api.get_slot_value_default(item, "n", 'float("inf")'),
},
"Action": lambda item: {
**name_dict(item),
"ports_exec_in": self.api.get_slot_value_default(item, "ports_exec_in", ["in"]),
"ports_exec_out": self.api.get_slot_value_default(item, "ports_exec_out", ["out"]),
"ports_data_in": self.api.get_slot_value_default(item, "ports_data_in", []),
"ports_data_out": self.api.get_slot_value_default(item, "ports_data_out", []),
"action": repr(self.api.get_slot_value(item, "action")),
"init": repr(
self.api.get_slot_value_default(item, "init", "")
),
},
"Modify": lambda item: {
**name_dict(item),
"rename": eval(self.api.get_slot_value_default(item, "rename", "{}")),
"delete": eval(self.api.get_slot_value_default(item, "delete", "{}")),
},
"Merge": lambda item: {
**name_dict(item),
"ports_data_in": eval(
self.api.get_slot_value_default(item, "ports_data_in", "[]")
),
},
"Store": lambda item: {
**name_dict(item),
"ports": eval(self.api.get_slot_value_default(item, "ports", "[]")),
},
"Schedule": file_dict,
"Print": lambda item: {
**name_dict(item),
"label": self.api.get_slot_value_default(item, "label", ""),
"custom": self.api.get_slot_value_default(item, "custom", ""),
},
"Conn_exec": (
conn_dict := lambda item: {
"name_from": self.api.get_name(self.api.get_source(item)),
"name_to": self.api.get_name(self.api.get_target(item)),
"from": self.api.get_slot_value_default(item, "from", 0),
"to": self.api.get_slot_value_default(item, "to", 0),
}
),
"Conn_data": lambda item: {
**conn_dict(item),
"event": conn_data_event[
self.api.get_type_name(target := self.api.get_target(item))
](target),
},
}
self.macro_args = {
tp: (macro, arg_map.get(tp))
for tp, macro in self.template.module.__dict__.items()
if type(macro) == Macro
}
def _render(self, item):
type_name = self.api.get_type_name(item)
macro, arg_gen = self.macro_args[type_name]
return macro(**arg_gen(item))
def _dfs(
self, stack: list[UUID], get_links: Callable, get_next_node: Callable
) -> tuple[set[UUID], list[UUID]]:
visited = set()
connections = list()
while len(stack) > 0:
obj = stack.pop()
if obj in visited:
continue
visited.add(obj)
for conn in get_links(self.api, obj):
connections.append(conn)
stack.append(get_next_node(self.api, conn))
return visited, connections
def generate_schedule(self, stream=sys.stdout):
start = self.api.get_all_instances("Start")[0][1]
end = self.api.get_all_instances("End")[0][1]
out = {
"blocks": [],
"blocks_name": [],
"blocks_start_end": [],
"exec_conn": [],
"data_conn": [],
"match_files": set(),
"matchers": [],
"start": self.api.get_name(start),
"end": self.api.get_name(end),
}
stack = [start, end]
exec_blocks, conn_exec = self._dfs(
stack,
lambda api, node: api.get_outgoing(node, "Conn_exec"),
lambda api, conn: api.get_target(conn),
)
for name, p in self.api.get_all_instances("Print"):
if self.api.has_slot(p, "event") and self.api.get_slot_value(p, "event"):
exec_blocks.add(p)
stack = list(exec_blocks)
blocks, conn_data = self._dfs(
stack,
lambda api, node: api.get_incoming(node, "Conn_data"),
lambda api, conn: api.get_source(conn),
)
for exec_c in conn_exec:
out["exec_conn"].append(self._render(exec_c))
for data_c in conn_data:
out["data_conn"].append(self._render(data_c))
for block in blocks:
out["blocks_name"].append(self.api.get_name(block))
if block in [start, end]:
out["blocks_start_end"].append(self._render(block))
continue
out["blocks"].append(self._render(block))
if self.api.is_instance(block, "Rule"):
d = self.macro_args[self.api.get_type_name(block)][1](block)
out["match_files"].add(d["file"])
out["matchers"].append(d)
print(self.template_wrap.render(out), file=stream)

View file

@ -0,0 +1,151 @@
from typing import TYPE_CHECKING, get_origin, get_args
from types import UnionType
from uuid import UUID
from jinja2 import Template
from framework.conformance import eval_context_decorator
from services.primitives.string_type import String
if TYPE_CHECKING:
from api.od_stub_readonly import get_outgoing, get_incoming, get_slot_value, get_value, get_target, has_slot
from eval_context_stub import *
@eval_context_decorator
def _check_all_connections(this, labels: list[list[str] | str]) -> list[str]:
err = []
check_incoming_exec(this, err, labels[0])
check_outgoing_exec(this, err, labels[1])
check_incoming_data(this, err, labels[2])
check_outgoing_data(this, err, labels[3])
return err
@eval_context_decorator
def _check_outgoing_exec(this, err: list[str], labels: list[str]) -> None:
l = set(labels)
gates = set()
for y in get_outgoing(this, "Conn_exec"):
if (x := get_slot_value(y, "from")) not in l:
err.append(f"output exec gate '{x}' does not exist. Gates: {', '.join(labels)}.")
if x in gates:
err.append(f"output exec gate '{x}' is connected to multiple gates.")
gates.add(x)
@eval_context_decorator
def _check_incoming_exec(this, err: list[str], labels: list[str]) -> None:
l = set(labels)
for y in get_incoming(this, "Conn_exec"):
if (x := get_slot_value(y, "to")) not in l:
err.append(f"input exec gate gate '{x}' does not exist. Gates: {', '.join(labels)}.")
@eval_context_decorator
def _check_outgoing_data(this, err: list[str], labels: list[str]) -> None:
l = set(labels)
for y in get_outgoing(this, "Conn_data"):
if (x := get_slot_value(y, "from")) not in l:
err.append(f"output data gate '{x}' does not exist. Gates: {', '.join(labels)}.")
@eval_context_decorator
def _check_incoming_data(this, err: list[str], labels: list[str]) -> None:
l = set(labels)
gates = set()
for y in get_incoming(this, "Conn_data"):
if (x := get_slot_value(y, "to")) not in l:
err.append(f"input data gate '{x}' does not exist. Gates: {', '.join(labels)}.")
if x in gates:
err.append(f"input data gate '{x}' is connected to multiple gates.")
gates.add(x)
def check_type(x: any, typ2: any) -> bool:
origin = get_origin(typ2)
if origin is None:
return isinstance(x, typ2)
args = get_args(typ2)
if origin is UnionType:
for tp in args:
if check_type(x, tp):
return True
return False
if not isinstance(x, origin):
return False
if origin in [list, set]:
for value in x:
if not check_type(value, args[0]):
return False
elif origin is tuple:
if len(args) != len(x):
return False
for i, value in enumerate(x):
if not check_type(value, args[i]):
return False
elif origin is dict:
for key, value in x.items():
if not (check_type(key, args[0]) and check_type(value, args[1])):
return False
return True
@eval_context_decorator
def _check_slot_code_type(this: UUID, slot: str, typ: type, unique = False, *, mandatory: bool = False, blacklist: list[str] | None = None) -> list[str]:
err = []
if not (has_slot(this, slot)):
if mandatory:
err.append(f"Missing mandatory slot: '{slot}'.")
return err
try:
try:
x = eval(get_slot_value(this, slot))
except Exception as _:
err.append(f"Invalid python code for {slot}: {get_slot_value(this, slot)}")
return err
if not check_type(x, typ):
try:
typ_rep = typ.__name__
except AttributeError:
typ_rep = str(typ)
err.append(f"Unexpected type for {slot}: {type(x).__name__}, expected type: {typ_rep}")
return err
if unique and len(set(x)) != len(x):
err.append(f"elements must be unique")
return err
except Exception as e:
err.append(f"Unexpected error: {e}")
return err
@eval_context_decorator
def _check_jinja2_code(this: UUID, slot: str) -> list[str]:
if len(err:= check_slot_code_type(this, slot, str, mandatory=True)) != 0:
return err
s = eval(get_slot_value(this, slot))
try:
template = Template(s)
template.render(**{"data":[{}]})
return []
except Exception as e:
return [f"Invalid Jinja2 syntax for '{slot}':\n{e}\n{s}"]
@eval_context_decorator
def _check_code_syntax(code) -> list[str]:
try:
compile(code, "<string>", "exec")
return []
except SyntaxError as e:
return [f"Invalid python code for: `{code}` :\n{e}"]
mm_eval_context = {
"check_all_connections": _check_all_connections,
"check_outgoing_exec": _check_outgoing_exec,
"check_incoming_exec": _check_incoming_exec,
"check_outgoing_data": _check_outgoing_data,
"check_incoming_data": _check_incoming_data,
"check_slot_code_type": _check_slot_code_type,
"check_code_syntax": _check_code_syntax,
"check_jinja2_code": _check_jinja2_code,
}

View file

@ -0,0 +1,6 @@
def check_outgoing_exec(this, err: list[str], labels: list[str]) -> bool: ...
def check_incoming_exec(this, err: list[str], labels: list[str]) -> bool: ...
def check_outgoing_data(this, err: list[str], labels: list[str]) -> bool: ...
def check_incoming_data(this, err: list[str], labels: list[str]) -> bool: ...
def check_is_type(s: str, typ: any) -> bool: ...
def check_code_syntax(code) -> bool: ...

View file

@ -0,0 +1,195 @@
abstract class Exec
association Conn_exec [0..*] Exec -> Exec [0..*] {
String from;
String to;
}
abstract class Data
association Conn_data [0..*] Data -> Data [0..*] {
Integer from;
Integer to;
}
abstract class Node (Exec, Data)
class Start [1..1] (Node) {
optional ActionCode ports_exec_out;
optional ActionCode ports_data_out;
```
err = check_slot_code_type(this, "ports_exec_out", list[str] | set[str], True)
err.extend(check_slot_code_type(this, "ports_data_out", list[str] | set[str], True))
if len(err) == 0:
err = check_all_connections(this, [
[],
eval(get_slot_value_default(this, "ports_exec_out", "['out']")),
[],
eval(get_slot_value_default(this, "ports_data_out", "[]"))
])
err
```;
}
class End [1..1] (Node) {
optional ActionCode ports_exec_in;
optional ActionCode ports_data_in;
```
err = check_slot_code_type(this, "ports_exec_in", list[str] | set[str], True)
err.extend(check_slot_code_type(this, "ports_data_in", list[str] | set[str], True))
if len(err) == 0:
err = check_all_connections(this, [
eval(get_slot_value_default(this, "ports_exec_in", "['in']")),
[],
eval(get_slot_value_default(this, "ports_data_in", "[]")),
[]
])
err
```;
}
abstract class Rule (Node)
{
String file;
}
class Match (Rule)
{
optional Integer n;
```
check_all_connections(this, [
["in"],
["success", "fail"],
["in"],
["out"]
])
```;
}
class Rewrite (Rule)
{
```
check_all_connections(this, [
["in"],
["out"],
["in"],
["out"]
])
```;
}
class Action (Node)
{
optional ActionCode ports_exec_in;
optional ActionCode ports_exec_out;
optional ActionCode ports_data_in;
optional ActionCode ports_data_out;
optional ActionCode init `check_code_syntax(get_value(get_target(this)))`;
ActionCode action `check_code_syntax(get_value(get_target(this)))`;
```
err = check_slot_code_type(this, "ports_exec_in", list[str] | set[str], True)
err.extend(check_slot_code_type(this, "ports_exec_out", list[str] | set[str], True))
err.extend(check_slot_code_type(this, "ports_data_in", list[str] | set[str], True))
err.extend(check_slot_code_type(this, "ports_data_out", list[str] | set[str], True))
if len(err) == 0:
err = check_all_connections(this, [
eval(get_slot_value_default(this, "ports_exec_in", "['in']")),
eval(get_slot_value_default(this, "ports_exec_out", "['out']")),
eval(get_slot_value_default(this, "ports_data_in", "[]")),
eval(get_slot_value_default(this, "ports_data_out", "[]"))
])
err
```;
}
class Modify (Node)
{
optional ActionCode rename;
optional ActionCode delete;
```
err = check_slot_code_type(this, "rename", dict[str,str])
err.extend(check_slot_code_type(this, "delete", list[str] | set[str]))
if len(err) == 0:
if not (eval(get_slot_value_default(this, "rename", "dict()")).keys().isdisjoint(
eval(get_slot_value_default(this, "delete", "set()")))
):
err.append("rename and delete should be disjoint.")
err.extend(check_all_connections(this, [
[],
[],
["in"],
["out"]
]))
err
```;
}
class Merge (Node)
{
ActionCode ports_data_in;
```
err = check_slot_code_type(this, "ports_data_in", list[str] | set[str], True, mandatory = True)
if len(err) == 0:
err = check_all_connections(this, [
[],
[],
eval(get_slot_value(this, "ports_data_in")),
["out"]
])
err
```;
}
class Store (Node)
{
ActionCode ports;
```
err = check_slot_code_type(this, "ports", list[str] | set[str], True, mandatory = True, blacklist = ["in", "out"])
if len(err) == 0:
err = check_all_connections(this, [
[*(ports:= eval(get_slot_value(this, "ports"))), "in"],
[*ports, "out"],
ports,
["out"]
])
err
```;
}
class Schedule (Node)
{
String file;
```
check_all_connections(this, [
{get_slot_value(conn, "to") for conn in get_incoming(this, "Conn_exec")},
{get_slot_value(conn, "from") for conn in get_outgoing(this, "Conn_exec")},
{get_slot_value(conn, "to") for conn in get_incoming(this, "Conn_data")},
{get_slot_value(conn, "from") for conn in get_outgoing(this, "Conn_data")}
])
```;
}
class Loop(Node)
{
```
check_all_connections(this, [
["in"],
["it", "out"],
["in"],
["out"]
])
```;
}
class Print(Node)
{
optional Boolean event;
optional String label;
optional ActionCode custom `check_jinja2_code(get_source(this), "custom")`;
```
check_all_connections(this, [
["in"],
["out"],
["in"],
[]
])
```;
}

View file

@ -0,0 +1,46 @@
from typing import Any
from uuid import UUID
from api.od import ODAPI
from transformation.matcher import match_od
from transformation.rewriter import rewrite
from util.loader import parse_and_check
class RuleExecutor:
def __init__(self, state, mm: UUID, mm_ramified: UUID, eval_context={}):
self.state = state
self.mm = mm
self.mm_ramified = mm_ramified
self.eval_context = eval_context
# Generates matches.
# Every match is a dictionary with entries LHS_element_name -> model_element_name
def match_rule(self, m: UUID, lhs: UUID, *, pivot: dict[Any, Any]):
lhs_matcher = match_od(
self.state,
host_m=m,
host_mm=self.mm,
pattern_m=lhs,
pattern_mm=self.mm_ramified,
eval_context=self.eval_context,
pivot=pivot,
)
return lhs_matcher
def rewrite_rule(self, od: ODAPI, rhs: UUID, *, pivot: dict[Any, Any]):
rhs = rewrite(
self.state,
rhs_m=rhs,
pattern_mm=self.mm_ramified,
lhs_match=pivot,
host_m=od.m,
host_mm=od.mm,
eval_context=self.eval_context,
)
od.recompute_mappings()
yield rhs
def load_match(self, file: str):
with open(file, "r") as f:
return parse_and_check(self.state, f.read(), self.mm_ramified, file)

View file

@ -0,0 +1,338 @@
from __future__ import annotations
import importlib.util
import io
import os
import re
import sys
from pathlib import Path
from time import time
from typing import cast, TYPE_CHECKING
from jinja2 import FileSystemLoader, Environment
from concrete_syntax.textual_od import parser as parser_od
from concrete_syntax.textual_cd import parser as parser_cd
from api.od import ODAPI
from bootstrap.scd import bootstrap_scd
from transformation.schedule.rule_executor import RuleExecutor
from transformation.schedule.generator import schedule_generator
from transformation.schedule.models.eval_context import mm_eval_context
from transformation.schedule.schedule_lib import ExecNode, Start
from framework.conformance import Conformance, render_conformance_check_result, eval_context_decorator
from state.devstate import DevState
from examples.petrinet.renderer import render_petri_net_to_dot
from drawio2py import parser
from drawio2py.abstract_syntax import DrawIOFile, Edge, Vertex, Cell
from icecream import ic
from transformation.schedule.schedule_lib.funcs import IdGenerator
if TYPE_CHECKING:
from transformation.schedule.schedule import Schedule
class RuleSchedular:
__slots__ = (
"rule_executor",
"schedule_main",
"loaded",
"out",
"verbose",
"conformance",
"directory",
"eval_context",
"_state",
"_mmm_cs",
"sub_schedules",
"end_time",
)
def __init__(
self,
state,
mm_rt,
mm_rt_ramified,
*,
outstream=sys.stdout,
verbose: bool = False,
conformance: bool = True,
directory: str = "",
eval_context: dict[str, any] = None,
):
self.rule_executor: RuleExecutor = RuleExecutor(state, mm_rt, mm_rt_ramified)
self.schedule_main: Schedule | None = None
self.out = outstream
self.verbose: bool = verbose
self.conformance: bool = conformance
self.directory: Path = Path.cwd() / directory
if eval_context is None:
eval_context = {}
self.eval_context: dict[str, any] = eval_context
self.loaded: dict[str, dict[str, any]] = {"od": {}, "py": {}, "drawio": {}, "rules": {}}
self._state = DevState()
self._mmm_cs = bootstrap_scd(self._state)
self.end_time = float("inf")
self.sub_schedules = float("inf")
def load_schedule(self, filename):
return self._load_schedule(filename, _main=True) is not None
def _load_schedule(self, filename: str, *, _main = True) -> Schedule | None:
if filename.endswith(".drawio"):
if (filename := self._generate_schedule_drawio(filename)) is None:
return None
if filename.endswith(".od"):
if (filename := self._generate_schedule_od(filename)) is None:
return None
if filename.endswith(".py"):
s = self._load_schedule_py(filename, _main=_main)
return s
raise Exception(f"Error unknown file: {filename}")
def _load_schedule_py(self, filename: str, *, _main = True) -> "Schedule":
if (s:= self.loaded["py"].get(filename, None)) is not None:
return s
spec = importlib.util.spec_from_file_location(filename, str(self.directory / filename))
schedule_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(schedule_module)
self.loaded["py"][filename] = (s:= schedule_module.Schedule())
if _main:
self.schedule_main = s
self.load_matchers(s)
return s
def _generate_schedule_od(self, filename: str) -> str | None:
if (s:= self.loaded.get(("od", filename), None)) is not None:
return s
file = str(self.directory / filename)
self._print("Generating schedule ...")
with open(f"{os.path.dirname(__file__)}/models/scheduling_MM.od", "r") as f_MM:
mm_cs = f_MM.read()
try:
with open(file, "r") as f_M:
m_cs = f_M.read()
except FileNotFoundError:
self._print(f"File not found: {file}")
return None
self._print("OK\n\nParsing models\n\tParsing meta model")
try:
scheduling_mm = parser_cd.parse_cd(
self._state,
m_text=mm_cs,
)
except Exception as e:
self._print(
f"Error while parsing meta-model: scheduling_MM.od\n\t{e}"
)
return None
self._print(f"\tParsing '{filename}' model")
try:
scheduling_m = parser_od.parse_od(
self._state, m_text=m_cs, mm=scheduling_mm
)
except Exception as e:
self._print(f"\033[91mError while parsing model: {filename}\n\t{e}\033[0m")
return None
if self.conformance:
success = True
self._print("OK\n\tmeta-meta-model a valid class diagram")
conf_err = Conformance(
self._state, self._mmm_cs, self._mmm_cs
).check_nominal()
b = len(conf_err)
success = success and not b
self._print(
f"\t\t{'\033[91m' if b else ''}{render_conformance_check_result(conf_err)}{'\033[0m' if b else ''}"
)
self._print(
f"Is our '{filename}' model a valid 'scheduling_MM.od' diagram?"
)
conf_err = Conformance(
self._state, scheduling_m, scheduling_mm, eval_context=mm_eval_context
).check_nominal()
b = len(conf_err)
success = success and not b
self._print(
f"\t\t{'\033[91m' if b else ''}{render_conformance_check_result(conf_err)}{'\033[0m' if b else ''}"
)
if not success:
return None
od = ODAPI(self._state, scheduling_m, scheduling_mm)
g = schedule_generator(od)
output_buffer = io.StringIO()
g.generate_schedule(output_buffer)
outfilename = f"{".".join(filename.split(".")[:-1])}.py"
open(self.directory / outfilename, "w", encoding='utf-8').write(output_buffer.getvalue())
self._print("Schedule generated")
self.loaded[("od", filename)] = outfilename
return outfilename
def _print(self, *args) -> None:
if self.verbose:
print(*args, file=self.out)
def load_matchers(self, schedule: "Schedule") -> None:
matchers = dict()
for file in schedule.get_matchers():
if (r:= self.loaded.get(("rule", file), None)) is None:
self.loaded[("rule", file)] = (r:= self.rule_executor.load_match(self.directory / file))
matchers[file] = r
schedule.init_schedule(self, self.rule_executor, matchers)
def generate_dot(self, file: str) -> None:
env = Environment(
loader=FileSystemLoader(
os.path.join(os.path.dirname(__file__), "templates")
)
)
env.trim_blocks = True
env.lstrip_blocks = True
template_dot = env.get_template("schedule_dot.j2")
nodes = []
edges = []
visit = set()
for schedule in self.loaded["py"].values():
schedule.generate_dot(nodes, edges, visit, template_dot)
with open(self.directory / file, "w") as f_dot:
f_dot.write(template_dot.render(nodes=nodes, edges=edges))
def run(self, model) -> tuple[int, str]:
self._print("Start simulation")
if 'pydevd' in sys.modules:
self.end_time = time() + 1000
else:
self.end_time = time() + 10000
return self._runner(model, self.schedule_main, "out", IdGenerator.generate_exec_id(), {})
def _runner(self, model, schedule: Schedule, exec_port: str, exec_id: int, data: dict[str, any]) -> tuple[int, any]:
self._generate_stackframe(schedule, exec_id)
cur_node = schedule.start
cur_node.run_init(exec_port, exec_id, data)
while self.end_time > time():
cur_node, port = cur_node.nextState(exec_id)
termination_reason = cur_node.execute(port, exec_id, model)
if termination_reason is not None:
self._delete_stackframe(schedule, exec_id)
return termination_reason
self._delete_stackframe(schedule, exec_id)
return -1, "limit reached"
def _generate_stackframe(self, schedule: Schedule, exec_id: int) -> None:
for node in schedule.nodes:
node.generate_stack_frame(exec_id)
def _delete_stackframe(self, schedule: Schedule, exec_id: int) -> None:
for node in schedule.nodes:
node.delete_stack_frame(exec_id)
def _generate_schedule_drawio(self, filename:str) -> str | None:
if (s:= self.loaded["drawio"].get(filename, None)) is not None:
return s
env = Environment(
loader=FileSystemLoader(
os.path.join(os.path.dirname(__file__), "templates")
)
)
env.trim_blocks = True
env.lstrip_blocks = True
template = env.get_template("schedule_muMLE.j2")
main: bool = False
node_map: dict[str, list[str | dict[str,str]]]
id_counter: int
def _get_node_id_map(elem: Cell) -> list[str | dict[str,str]]:
nonlocal node_map, id_counter
if (e_id := node_map.get(elem.id, None)) is None:
e_id = [f"{re.sub(r'[^a-zA-Z1-9_]', '', elem.properties["name"])}_{id_counter}", {}]
id_counter += 1
node_map[elem.id] = e_id
return e_id
edges: list[tuple[tuple[str, str, str, str], tuple[str,str,str,str]]] = []
def _parse_edge(elem: Edge):
nonlocal edges
try:
edges.append((
(
_get_node_id_map(elem.source.parent.parent.parent)[0],
elem.source.properties["label"],
elem.source.properties["type"],
elem.source.parent.value
),
(
_get_node_id_map(elem.target.parent.parent.parent)[0],
elem.target.properties["label"],
elem.target.properties["type"],
elem.target.parent.value
)
))
except AttributeError as e:
raise Exception(f"Missing attribute {e}")
return
def _parse_vertex(elem: Vertex):
nonlocal edges
try:
elem_map = _get_node_id_map(elem)
elem_map[1] = elem.properties
properties = elem_map[1]
properties.pop("label")
properties.pop("name")
properties.pop("placeholders")
if properties.get("type") == "Schedule":
if not re.search(r'\.(py|od)$', properties["file"]):
properties["file"] = f"{filename}/{properties["file"]}.od"
except AttributeError as e:
raise Exception(f"Missing attribute {e}")
return
abstract_syntax: DrawIOFile = parser.Parser.parse(str(self.directory / filename))
filename = filename.removesuffix(".drawio")
(self.directory / filename).mkdir(parents=False, exist_ok=True)
for page in abstract_syntax.pages:
if page.name == "main":
main = True
if len(page.root.children) != 1:
raise Exception(f"Only 1 layer allowed (keybind: ctr+shift+L)")
edges = []
id_counter = 1
node_map = {}
for element in page.root.children[0].children:
match element.__class__.__name__:
case "Edge":
_parse_edge(cast(Edge, element))
case "Vertex":
_parse_vertex(cast(Vertex, element))
for elem in element.children[0].children:
if elem.__class__.__name__ == "Edge":
_parse_edge(cast(Edge, elem))
continue
case _:
raise Exception(f"Unexpected element: {element}")
with open(self.directory / f"{filename}/{page.name}.od", "w", encoding="utf-8") as f:
f.write(template.render(nodes=node_map, edges=edges))
if main:
self.loaded["drawio"][filename] = (filename_out := f"{filename}/main.od")
return filename_out
self._print("drawio schedule requires main page to automatically load.")
return None

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