add petri net renderer (graphviz-based)

This commit is contained in:
Joeri Exelmans 2024-11-21 14:58:32 +01:00
parent a0eb56421f
commit 3aec288e37
3 changed files with 33 additions and 2 deletions

View file

@ -1,12 +1,12 @@
from concrete_syntax.common import indent from concrete_syntax.common import indent
import urllib.parse 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}}" as_digraph = f"digraph {{\n{indent(graphviz_txt, 2)}\n}}"
# This one seems much faster: # 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: # Keeping this one here just in case:
# return "https://dreampuf.github.io/GraphvizOnline/#"+urllib.parse.quote(graphviz) # return "https://dreampuf.github.io/GraphvizOnline/#"+urllib.parse.quote(graphviz)

View file

@ -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")

View file

@ -5,6 +5,7 @@ from util import loader
from transformation.rule import RuleMatcherRewriter, ActionGenerator from transformation.rule import RuleMatcherRewriter, ActionGenerator
from transformation.ramify import ramify from transformation.ramify import ramify
from examples.semantics.operational import simulator from examples.semantics.operational import simulator
from examples.petrinet.renderer import render_petri_net
if __name__ == "__main__": if __name__ == "__main__":
@ -49,6 +50,7 @@ if __name__ == "__main__":
action_generator=action_generator, action_generator=action_generator,
decision_maker=simulator.InteractiveDecisionMaker(auto_proceed=False), decision_maker=simulator.InteractiveDecisionMaker(auto_proceed=False),
# decision_maker=simulator.RandomDecisionMaker(seed=0), # decision_maker=simulator.RandomDecisionMaker(seed=0),
renderer=render_petri_net,
) )
sim.run(ODAPI(state, m_rt_initial, mm_rt)) sim.run(ODAPI(state, m_rt_initial, mm_rt))