Advertisement
Guest User

Untitled

a guest
Sep 19th, 2019
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.56 KB | None | 0 0
  1. import graphviz
  2.  
  3. class State:
  4.  
  5. def __init__(self, name, style="solid", color="black"):
  6. self.name = name
  7. self.style = style
  8. self.color = color
  9.  
  10. self.rendered = False
  11.  
  12. def set_style(self, style):
  13. self.style = style
  14.  
  15. def __eq__(self, other):
  16. if self.name == other:
  17. return True
  18. else:
  19. return False
  20. def __str__(self):
  21. return self.name
  22.  
  23. def __repr__(self):
  24. return self.name
  25.  
  26. def render(self, graph):
  27. graph.node(self.name, style=self.style, color=self.color)
  28.  
  29.  
  30. class automata:
  31.  
  32. def __init__(self, state_names, alphabet, start_state, final_states):
  33. self.alphabet = alphabet
  34. self.start_state = start_state
  35. self.final_states = final_states
  36. self.edges = list()
  37. self.states = list()
  38. self.graph = None
  39.  
  40.  
  41. for state_name in state_names:
  42. style= None
  43. if state_name == start_state:
  44. self.states.append(State("", style="invis"))
  45. style = "bold"
  46. self.edges.append(["", state_name, ""])
  47. if state_name in final_states:
  48. style = "dashed"
  49.  
  50. self.states.append(State(state_name, style = style))
  51.  
  52. return
  53.  
  54. def __remove_invisible(self):
  55. new_states = list()
  56. new_edges = list()
  57.  
  58. for state in self.states:
  59. if state.style == "invis" or state.name == "":
  60. print("Style is invisible")
  61. continue
  62. else:
  63. new_states.append(state)
  64. for edge in self.edges:
  65. if edge[0] == "":
  66. print("Edge is blank")
  67. continue
  68. else:
  69. new_edges.append(edge)
  70. self.states = new_states
  71. self.edges = new_edges
  72.  
  73.  
  74.  
  75. def __rename_states(self, name_postfix):
  76. renamed_states = list()
  77. renamed_edges = list()
  78. renamed_final_states = list()
  79.  
  80. for s in self.states:
  81. if len(s.name) <= 0:
  82. break
  83. renamed_states.append(str(s)+str(name_postfix))
  84. for e in self.edges:
  85. if len(e[0]) <= 0:
  86. renamed_edges.append([e[0], e[1]+str(name_postfix), e[2]])
  87.  
  88. renamed_edges.append([e[0]+str(name_postfix), e[1]+str(name_postfix), e[2]])
  89. for s in self.final_states:
  90. renamed_final_states.append(s+str(name_postfix))
  91.  
  92.  
  93. self.states = renamed_states
  94. self.edges = renamed_edges
  95. self.final_states = renamed_final_states
  96. self.start_state = self.start_state+str(name_postfix)
  97.  
  98. def __copy(self):
  99. a = automata([str(s) for s in self.states[1:]], self.alphabet, self.start_state, self.final_states)
  100. a.edges = self.edges
  101. return a
  102.  
  103. def from_union(automatons):
  104.  
  105. new_states = list()
  106. new_edges = list()
  107. new_final_states = list()
  108.  
  109. copied_automatons = list()
  110.  
  111. for a in automatons:
  112. copied_automatons.append(a.__copy())
  113.  
  114.  
  115. i = 0
  116. for a in copied_automatons:
  117. a.__remove_invisible()
  118. a.__rename_states(i)
  119.  
  120. new_states += a.states
  121. new_edges += a.edges
  122. new_final_states += a.final_states
  123. i = i+1
  124.  
  125. new_states.append("start")
  126.  
  127. for a in copied_automatons:
  128. new_edges.append(["start", a.start_state, "ε"])
  129.  
  130. new_automaton = automata(new_states, automatons[0].alphabet, "start", new_final_states)
  131. new_automaton.edges = new_automaton.edges + new_edges
  132.  
  133. return new_automaton
  134.  
  135. def from_concat(automatons):
  136. copied_automatons = list()
  137.  
  138. for a in automatons:
  139. copied_automatons.append(a.__copy())
  140.  
  141. i = 0
  142. for a in copied_automatons:
  143. a.__remove_invisible()
  144. a.__rename_states(i)
  145. i+=1
  146.  
  147. first_automaton = copied_automatons[0]
  148.  
  149.  
  150. new_states = list()
  151. new_edges = list()
  152. new_final_states = list()
  153.  
  154. for a in copied_automatons:
  155. new_states += a.states
  156. new_edges += a.edges
  157. new_final_states += a.final_states
  158.  
  159.  
  160. new_automaton = automata(new_states, copied_automatons[0], copied_automatons[0].start_state, new_final_states)
  161.  
  162. new_automaton.edges = new_edges
  163.  
  164. for i in range(len(copied_automatons)):
  165. last_a = copied_automatons[i]
  166. if i != len(copied_automatons)-1:
  167. next_a = copied_automatons[i+1]
  168. else:
  169. break
  170. for state in last_a.final_states:
  171. pass
  172. new_automaton.edge(state, next_a.start_state, "ε")
  173.  
  174. return new_automaton
  175.  
  176. def from_star(automaton):
  177. copied_automaton = automaton.__copy()
  178.  
  179. copied_automaton.__remove_invisible()
  180.  
  181. for state in copied_automaton.final_states:
  182. copied_automaton.edge(state, copied_automaton.start_state, "ε")
  183.  
  184. copied_automaton.states[0].style = "solid"
  185. copied_automaton.states.append(State("start"))
  186. copied_automaton.edge("start", copied_automaton.start_state, "ε")
  187. copied_automaton.start_state = "start"
  188.  
  189.  
  190. return copied_automaton
  191.  
  192.  
  193. def _check_start_end(self):
  194. for state in self.states:
  195. if state.name == "":
  196. continue
  197. if state.name == self.start_state:
  198. state.style = "bold"
  199. if state.name in self.final_states:
  200. state.style = "dashed"
  201. return
  202.  
  203.  
  204. def edge(self, source, dest, rule):
  205. self.edges.append([source, dest, " "+rule])
  206. if source not in self.states:
  207. self.states.append(State(source))
  208. self._check_start_end()
  209. if dest not in self.states:
  210. self.states.append(State(dest))
  211. self._check_start_end()
  212. return
  213.  
  214. def _repr_svg_(self):
  215. self.graph = graphviz.Digraph()
  216.  
  217. self._check_start_end() # Update if we changed/added the start/end states since making this obeject
  218.  
  219. for state in self.states:
  220. state.render(self.graph)
  221.  
  222. for e in self.edges:
  223. self.graph.edge(e[0], e[1], label=e[2])
  224.  
  225. return self.graph._repr_svg_()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement