|
@@ -0,0 +1,154 @@
|
|
|
|
+import subprocess
|
|
|
|
+
|
|
|
|
+try:
|
|
|
|
+ import pydot
|
|
|
|
+
|
|
|
|
+ has_pydot = True
|
|
|
|
+except ImportError:
|
|
|
|
+ has_pydot = False
|
|
|
|
+
|
|
|
|
+class LoLADraw:
|
|
|
|
+
|
|
|
|
+ def __init__(self):
|
|
|
|
+ print("Starting LoLADraw...")
|
|
|
|
+ print("Please ensure that GraphViz is installed before use.")
|
|
|
|
+
|
|
|
|
+ def get_net(self, filename):
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ places = []
|
|
|
|
+ markings = {}
|
|
|
|
+ transitions = {}
|
|
|
|
+
|
|
|
|
+ place_mode = False
|
|
|
|
+ marking_mode = False
|
|
|
|
+ transition_mode = False
|
|
|
|
+
|
|
|
|
+ trans_consume_mode = True
|
|
|
|
+ trans_name = ""
|
|
|
|
+ trans_consume = {}
|
|
|
|
+ trans_produce = {}
|
|
|
|
+
|
|
|
|
+ with open(filename) as f:
|
|
|
|
+
|
|
|
|
+ for line in f:
|
|
|
|
+ if "PLACE" in line:
|
|
|
|
+ place_mode = True
|
|
|
|
+ continue
|
|
|
|
+ elif "MARKING" in line:
|
|
|
|
+ place_mode = False
|
|
|
|
+ marking_mode = True
|
|
|
|
+ continue
|
|
|
|
+ elif "TRANSITION" in line:
|
|
|
|
+ marking_mode = False
|
|
|
|
+ transition_mode = True
|
|
|
|
+
|
|
|
|
+ line = line.strip()
|
|
|
|
+ if not line:
|
|
|
|
+ continue
|
|
|
|
+
|
|
|
|
+ print(line)
|
|
|
|
+ if place_mode:
|
|
|
|
+ if "SAFE" in line:
|
|
|
|
+ continue
|
|
|
|
+ for place in line.split(','):
|
|
|
|
+ place = place.replace(";", "").strip()
|
|
|
|
+ if place:
|
|
|
|
+ places.append(place)
|
|
|
|
+ elif marking_mode:
|
|
|
|
+ for marking in line.split(','):
|
|
|
|
+ if not marking:
|
|
|
|
+ continue
|
|
|
|
+ m = marking.split(":")
|
|
|
|
+ markings[m[0].strip()] = m[1].replace(";", "").strip()
|
|
|
|
+ elif transition_mode:
|
|
|
|
+ if "TRANSITION" in line:
|
|
|
|
+
|
|
|
|
+ if trans_name:
|
|
|
|
+ transitions[trans_name] = (trans_consume, trans_produce)
|
|
|
|
+ trans_consume = {}
|
|
|
|
+ trans_produce = {}
|
|
|
|
+
|
|
|
|
+ trans_name = line.split(" ")[1]
|
|
|
|
+
|
|
|
|
+ elif trans_consume_mode:
|
|
|
|
+
|
|
|
|
+ if "CONSUME" in line:
|
|
|
|
+ continue
|
|
|
|
+ elif "PRODUCE" in line:
|
|
|
|
+ trans_consume_mode = False
|
|
|
|
+ else:
|
|
|
|
+ for consume in line.split(","):
|
|
|
|
+ if not consume:
|
|
|
|
+ continue
|
|
|
|
+ place, marking = consume.split(":")
|
|
|
|
+ trans_consume[place.strip()] = marking.replace(";", "").strip()
|
|
|
|
+ elif not trans_consume_mode:
|
|
|
|
+ if ";" in line:
|
|
|
|
+ trans_consume_mode = True
|
|
|
|
+ for produce in line.split(","):
|
|
|
|
+ if not produce:
|
|
|
|
+ continue
|
|
|
|
+ place, marking = produce.split(":")
|
|
|
|
+ trans_produce[place.strip()] = marking.replace(";", "").strip()
|
|
|
|
+
|
|
|
|
+ # do end-of-file
|
|
|
|
+ if trans_name:
|
|
|
|
+ transitions[trans_name] = (trans_consume, trans_produce)
|
|
|
|
+ return places, markings, transitions
|
|
|
|
+
|
|
|
|
+ def draw(self, filename):
|
|
|
|
+
|
|
|
|
+ name = filename.replace(".lola", "")
|
|
|
|
+ nodes = {}
|
|
|
|
+ graph = pydot.Dot(name, graph_type='digraph', layout='neato')
|
|
|
|
+
|
|
|
|
+ places, markings, transitions = self.get_net(filename)
|
|
|
|
+ print("Places: " + str(places))
|
|
|
|
+ print("Markings: " + str(markings))
|
|
|
|
+ print("Transitions: " + str(transitions))
|
|
|
|
+
|
|
|
|
+ for i, place in enumerate(places):
|
|
|
|
+ v_attr = place
|
|
|
|
+ if place in markings:
|
|
|
|
+ v_attr += "\n" + markings[place]
|
|
|
|
+
|
|
|
|
+ nodes[place] = pydot.Node(v_attr, style="filled", fillcolor='lightblue')
|
|
|
|
+ graph.add_node(nodes[place])
|
|
|
|
+
|
|
|
|
+ for t_name, _ in transitions.items():
|
|
|
|
+ v_attr = t_name
|
|
|
|
+
|
|
|
|
+ nodes[t_name] = pydot.Node(v_attr, style="filled")
|
|
|
|
+ graph.add_node(nodes[t_name])
|
|
|
|
+
|
|
|
|
+ for t_name, conpro in transitions.items():
|
|
|
|
+ c, p = conpro
|
|
|
|
+
|
|
|
|
+ for c_name, weight in c.items():
|
|
|
|
+ graph.add_edge(pydot.Edge(nodes[c_name], nodes[t_name]))#, color=color))
|
|
|
|
+
|
|
|
|
+ for p_name, weight in p.items():
|
|
|
|
+ graph.add_edge(pydot.Edge(nodes[t_name], nodes[p_name], label=weight))
|
|
|
|
+ # , color=color))
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ dot_filename = filename.replace(".lola", ".dot")
|
|
|
|
+ graph.write(dot_filename, prog='dot')
|
|
|
|
+
|
|
|
|
+ command = "dot -Tsvg " + dot_filename + " -o " + filename.replace(".lola", ".svg")
|
|
|
|
+ subprocess.call(command, shell=True)
|
|
|
|
+
|
|
|
|
+ # command = "rm " + dot_filename
|
|
|
|
+ # subprocess.call(command, shell=True)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+if __name__ == "__main__":
|
|
|
|
+
|
|
|
|
+ if not has_pydot:
|
|
|
|
+ print("ERROR: Install pydot first!")
|
|
|
|
+ exit(1)
|
|
|
|
+
|
|
|
|
+ filename = "dining_philo.lola"
|
|
|
|
+ ld = LoLADraw()
|
|
|
|
+ ld.draw(filename)
|