소스 검색

add petri net renderer (graphviz-based)

Joeri Exelmans 1 년 전
부모
커밋
3aec288e37
3개의 변경된 파일33개의 추가작업 그리고 2개의 파일을 삭제
  1. 2 2
      concrete_syntax/graphviz/make_url.py
  2. 29 0
      examples/petrinet/renderer.py
  3. 2 0
      examples/petrinet/runner.py

+ 2 - 2
concrete_syntax/graphviz/make_url.py

@@ -1,12 +1,12 @@
 from concrete_syntax.common import indent
 import urllib.parse
 
-def make_url(graphviz_txt: str) -> str:
+def make_url(graphviz_txt: str, engine="dot") -> str:
 
     as_digraph = f"digraph {{\n{indent(graphviz_txt, 2)}\n}}"
 
     # This one seems much faster:
-    return "https://edotor.net/?engine=dot#"+urllib.parse.quote(as_digraph)
+    return f"https://edotor.net/?engine={engine}#{urllib.parse.quote(as_digraph)}"
 
     # Keeping this one here just in case:
     # return "https://dreampuf.github.io/GraphvizOnline/#"+urllib.parse.quote(graphviz)

+ 29 - 0
examples/petrinet/renderer.py

@@ -0,0 +1,29 @@
+from api.od import ODAPI
+from concrete_syntax.graphviz.make_url import make_url
+
+def render_petri_net(od: ODAPI):
+    dot = ""
+    dot += "rankdir=LR;"
+    dot += "center=true;"
+    dot += "margin=1;"
+    dot += "nodesep=1;"
+    dot += "edge [arrowhead=vee];"
+    dot += "node[fontname=Arial,fontsize=10];\n"
+    dot += "subgraph places {"
+    dot += "  node [shape=circle,fixedsize=true,label=\"\", height=.3,width=.3];"
+    for _, place_state in od.get_all_instances("PlaceState"):
+        place = od.get_target(od.get_outgoing(place_state, "of")[0])
+        place_name = od.get_name(place)
+        num_tokens = od.get_slot_value(place_state, "numTokens")
+        dot += f"  {place_name} [label=\"{place_name}\\n\\n{'●'*num_tokens}\\n\\n­\"];\n"
+    dot += "}\n"
+    dot += "subgraph transitions {"
+    dot += "  node [shape=rect,fixedsize=true,height=.4,width=.15,style=filled,fillcolor=black,color=white];\n"
+    for transition_name, _ in od.get_all_instances("Transition"):
+        dot += f"  {transition_name} [label=\"{transition_name}\\n\\n\\n\\n­\"];\n"
+    dot += "}\n"
+    for _, arc in od.get_all_instances("arc"):
+        src_name = od.get_name(od.get_source(arc))
+        tgt_name = od.get_name(od.get_target(arc))
+        dot += f"{src_name} -> {tgt_name};"
+    return make_url(dot, engine="circo")

+ 2 - 0
examples/petrinet/runner.py

@@ -5,6 +5,7 @@ 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 render_petri_net
 
 
 if __name__ == "__main__":
@@ -49,6 +50,7 @@ if __name__ == "__main__":
         action_generator=action_generator,
         decision_maker=simulator.InteractiveDecisionMaker(auto_proceed=False),
         # decision_maker=simulator.RandomDecisionMaker(seed=0),
+        renderer=render_petri_net,
     )
 
     sim.run(ODAPI(state, m_rt_initial, mm_rt))