瀏覽代碼

Initial commit.

bentleyjoakes 5 年之前
當前提交
355e8843f8
共有 3 個文件被更改,包括 364 次插入0 次删除
  1. 93 0
      .gitignore
  2. 117 0
      LoLAConvert.py
  3. 154 0
      LoLADraw.py

+ 93 - 0
.gitignore

@@ -0,0 +1,93 @@
+# IGNORE ALL INPUT/OUTPUT
+*.dot
+*.lola
+*.svg
+*.xml
+
+
+venv/
+
+# SVN
+.svn/
+
+# SVG figures for graphs
+dot/
+pic/
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# Profiling results
+*.lprof
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+bin/
+build/
+develop-eggs/
+dist/
+eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# Rope
+.ropeproject
+
+# Django stuff:
+*.log
+*.pot
+
+# Sphinx documentation
+docs/_build/
+
+#pycharm
+.idea
+.settings/
+
+*.py.bak
+
+*.DS_Store
+
+# Latex
+*.pptx#
+*.aux
+*.nav
+*.out
+*.snm
+*.synctex.gz
+*.toc
+
+*.bbl
+*.blg
+

+ 117 - 0
LoLAConvert.py

@@ -0,0 +1,117 @@
+import sys
+import xml.etree.ElementTree as ET
+
+class LoLAConvert:
+
+    def __init__(self):
+        pass
+
+    def convert_file(self, filename):
+
+        places, transitions, arcs = self.parse_pnml(filename)
+
+        print("Places: " + str(places))
+        print("Transitions: " + str(transitions))
+        print("Arcs: " + str(arcs))
+
+        places_with_markings = []
+        for place, marking in places.items():
+            if int(marking) > 0:
+                places_with_markings.append((place, marking))
+
+        lola_file = filename.replace(".xml", ".lola")
+        with open(lola_file, 'w') as f:
+            f.write("PLACE\n")
+
+            for i, place in enumerate(places):
+                f.write("\t" + place)
+                if i < len(places) -1:
+                    f.write(",\n")
+                else:
+                    f.write(";\n")
+
+            f.write("\nMARKING\n")
+            for i, pm in enumerate(places_with_markings):
+                f.write("\t" + pm[0] + " : " + pm[1])
+                if i < len(places_with_markings) -1:
+                    f.write(",\n")
+                else:
+                    f.write(";\n")
+
+            for trans in transitions:
+                f.write("\nTRANSITION " + trans + "\n")
+                consume = {}
+                produce = {}
+
+                for arc in arcs:
+                    s, t, w = arc
+                    if t == trans:
+                        consume[s] = w
+                    elif s == trans:
+                        produce[t] = w
+
+                f.write("\tCONSUME\n")
+                for i, s in enumerate(consume):
+                    f.write("\t\t" + s + " : " + consume[s])
+                    if i < len(consume) - 1:
+                        f.write(",\n")
+                    else:
+                        f.write(";\n")
+                f.write("\tPRODUCE\n")
+                for i, t in enumerate(produce):
+                    f.write("\t\t" + t + " : " + produce[t])
+                    if i < len(produce) - 1:
+                        f.write(",\n")
+                    else:
+                        f.write(";\n")
+
+    def parse_pnml(self, filename):
+        tree = ET.parse(filename)
+        root = tree.getroot()
+        net = root[0]
+
+        places = {}
+        transitions = []
+        arcs = []
+
+        for child in net:
+
+            if child.tag == "place":
+                name_node = self.get_child_with_name(child, "name")
+                name = self.get_child_with_name(name_node, "value").text
+
+                marking_node = self.get_child_with_name(child, 'initialMarking')
+                marking_value_node = self.get_child_with_name(marking_node, 'value')
+                marking = marking_value_node.text.split(",")[1]
+
+                places[name] = marking
+
+            elif child.tag == "transition":
+                name_node = self.get_child_with_name(child, "name")
+                name = self.get_child_with_name(name_node, "value").text
+
+                transitions.append(name)
+
+            elif child.tag == "arc":
+                source = child.get("source")
+                target = child.get("target")
+
+                inscription_node = self.get_child_with_name(child, 'inscription')
+                inscription_value_node = self.get_child_with_name(inscription_node, 'value')
+                inscription = inscription_value_node.text.split(",")[1]
+
+                arcs.append((source, target, inscription))
+
+
+        return places, transitions, arcs
+
+    def get_child_with_name(self, node, name):
+        for child in node:
+            if child.tag == name:
+                return child
+        raise Exception("On node: " + str(node) +", the child " + name + " was not found!")
+
+if __name__ == "__main__":
+    filename = "dining_philo.xml"
+    lc = LoLAConvert()
+    lc.convert_file(filename)

+ 154 - 0
LoLADraw.py

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