Advertisement
Guest User

Untitled

a guest
Mar 19th, 2019
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.59 KB | None | 0 0
  1. # Matthew Sloyan G00348036
  2. # https://github.com/MatthewSloyan/Graph-Theory-Project
  3.  
  4. def infixConversion(infix):
  5. """Shunting Yard Algorithm implementation for converting infix
  6. regular expressions to postfix."""
  7.  
  8. # declare the special operands and their priority. This will be updated down the line to add +- etc.
  9. specials = {'*': 50, '+': 50, '?': 50, '.': 40, '|': 30}
  10.  
  11. pofix, stack = "", ""
  12.  
  13. # interate through each character in the infix string
  14. for c in infix:
  15. # If and open bracket, push to the stack.
  16. if c == '(':
  17. stack = stack + c
  18. elif c == ')':
  19. # if the end of round brackets, add what's on the stack till '(' is encountered
  20. while stack[-1] != '(':
  21. pofix, stack = pofix + stack[-1], stack[:-1]
  22. # remove '(' from stack
  23. stack = stack[:-1]
  24. elif c in specials:
  25. # get(c, 0) = value in dictionary or return 0
  26. # push to stack if priority is lower or equal priority operators from top of stack into output.
  27. while stack and specials.get(c, 0) <= specials.get(stack[-1], 0):
  28. pofix, stack = pofix + stack[-1], stack[:-1]
  29. stack = stack + c
  30. else:
  31. pofix = pofix + c
  32.  
  33. # remove rest of elements from stack and print to postfix
  34. while stack:
  35. pofix, stack = pofix + stack[-1], stack[:-1]
  36.  
  37. return pofix
  38.  
  39. print(infixConversion("1|0"))
  40.  
  41. # Thompson's contruction
  42. # ======================
  43.  
  44. # Represents a state with two arrows, labelled by label.
  45. # Use None for a label representing 'e' arrows
  46. class state:
  47. # None = no value as of now but will assign
  48. label = None
  49. edge1 = None
  50. edge2 = None
  51.  
  52. # An NFA is represented by it's initial and accept states
  53. class nfa:
  54. initial = None
  55. accept = None
  56.  
  57. def __init__(self, initial, accept):
  58. self.initial = initial
  59. self.accept = accept
  60.  
  61. def compile(pofix):
  62. """Thompson's contruction implementation for converting postfix regular expressions
  63. into an equivalent nondeterministic finite automaton (NFA)."""
  64.  
  65. #initalise stack
  66. nfaStack = []
  67.  
  68. # interate through each character in the postfix string
  69. for c in pofix:
  70. if c == '.':
  71. # Pop Nfa's off the stack, nfa1 = first on stack
  72. nfa2 = nfaStack.pop()
  73. nfa1 = nfaStack.pop()
  74. # Connect first NFA's accept state to the second's initial.
  75. nfa1.accept.edge1 = nfa2.initial
  76. # Push NFA to the stack.
  77. nfaStack.append(nfa(nfa1.initial, nfa2.accept))
  78. elif c == '|':
  79. nfa2 = nfaStack.pop()
  80. nfa1 = nfaStack.pop()
  81. # Create a new initial state, connect it to initial states
  82. # of the two NFA's popped from the stack
  83. initial = state()
  84. initial.edge1 = nfa1.initial
  85. initial.edge2 = nfa2.initial
  86. # Create a new accept state, connecting the accept states
  87. # of the two NFA's popped from the stack, to the new state.
  88. accept = state()
  89. nfa1.accept.edge1 = accept
  90. nfa2.accept.edge1 = accept
  91. # Push new NFA to the stack
  92. nfaStack.append(nfa(initial, accept))
  93. elif c == '*':
  94. # Pop single NFA from the stack
  95. nfa1 = nfaStack.pop()
  96. # Create new intial and accepts states.
  97. initial = state()
  98. accept = state()
  99. # Join the new intial state to nfa1's initial state and the new accept state.
  100. initial.edge1 = nfa1.initial
  101. initial.edge2 = accept
  102. #join the old accept state to the new accept state and nfa1's initial state
  103. nfa1.accept.edge1 = nfa1.initial
  104. nfa1.accept.edge2 = accept
  105. #push new NFA to the stack.
  106. nfaStack.append(nfa(initial, accept))
  107. else:
  108. # Create new initial and accept states.
  109. accept = state()
  110. initial = state()
  111. # Joing the initial state, the accept state using an arrow labelled c.
  112. initial.label = c
  113. initial.edge1 = accept
  114. # Push new NFA to the stack.
  115. nfaStack.append(nfa(initial, accept)) # combine states
  116.  
  117. # nfaStack should only have a single nfa on it at this point
  118. return nfaStack.pop()
  119.  
  120. #print(compile("ab.cd.|"))
  121. #print(compile("aa.*"))
  122.  
  123. def followEs(state):
  124. """# Helper function, which returns set of states that can
  125. be reached from the state following e arrows."""
  126. # Create a new set, with state as it's only member.
  127. states = set()
  128. states.add(state)
  129.  
  130. # Check if state has arrows labelled e from it. (# If state = None, then e arrow)
  131. # Keep following e arrows as long as you can.
  132. if state.label is None:
  133. # Check if edge1 is a state.
  134. if state.edge1 is not None:
  135. # If there's an edge1, follow it and use recursion. | = union
  136. states |= followEs(state.edge1)
  137. # Check if edge2 is a state.
  138. if state.edge2 is not None:
  139. # If there's an edge2, follow it.
  140. states |= followEs(state.edge2)
  141.  
  142. # Return the set of states.
  143. return states
  144.  
  145. def match(infix, string):
  146. """# Shunt and compile the infix regular expression using both
  147. Shunting Yard Algorithm and Thompson's contruction functions."""
  148.  
  149. postfix = infixConversion(infix)
  150. # Creates nfa from postfix
  151. nfa = compile(postfix)
  152.  
  153. # The current set of states and the next set of states. Sets are like lists,
  154. # however can only contain unique values
  155. current = set()
  156. nextState = set()
  157.  
  158. # Add the initial state to the current set.
  159. current |= followEs(nfa.initial)
  160.  
  161. # Loop through each character in the postfix string
  162. for s in string:
  163. # Loop through current set of states.
  164. for c in current:
  165. # Check if that state is labelled s.
  166. if c.label == s:
  167. #print(c.label)
  168. # Add the edge 1 state to the next set.
  169. nextState |= followEs(c.edge1)
  170. # Set current to next, and clear out next.
  171. current = nextState
  172. nextState = set()
  173.  
  174. # Check if the accept state is in the set of current states.
  175. return(nfa.accept in current)
  176.  
  177. # Test match function
  178. infixes = ["1.2.3*", "a.(b|d).c*", "(a.(b|d))*", "a.(b.b)*.c"]
  179. strings = ["", "1233", "abbc", "abcc", "abad", "abbbc"]
  180.  
  181. for i in infixes:
  182. for s in strings:
  183. print(match(i, s), i, s)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement