def thompson(exp): """Fonction de transformation d'une expression postfixé en automate Algorithme prenant une expression régulière, et retournant l'automate de Thompson calculant le langage correspondant à cette expression. """ out_stack = prefix_regex(exp) print(out_stack) graph_stack = [] thompson_graph = Graph() operators = ['*', '.', '+'] states = [] for c in out_stack: # Si c'est un caractère # Créer un graphe avec un etat initial et etat final, et transition en lisant c if c not in operators: print("1-", c) g = Graph() print(len(graph_stack)) g.alphabet.append(c) # ajouter la lettre à l'alphabet i = gen_state(states) # générer l'état initial states.append(i) g.initialState = i g.states.append(i) j = gen_state(states) # générer l'état final states.append(j) g.finalStates.append(j) g.states.append(j) # ajouter la transition (initial, c, final) g.transitions.append(Transition(i, c, j)) # ajouter le graphe à la pile graph_stack.append(g) # Si elif c == '*': print("2-", c) g = Graph() g = graph_stack.pop() # récupérer le dernier graphe dans la pile print(len(graph_stack)) g.transitions.append( Transition(g.finalStates[0], '\u03b5', g.initialState)) i = gen_state(states) # générer l'état initial g.states.append(i) states.append(i) g.transitions.append(Transition(i, '\u03b5', g.initialState)) g.initialState = i j = gen_state(states) # générer l'état final g.states.append(j) states.append(j) g.transitions.append(Transition(g.finalStates[0], '\u03b5', j)) g.finalStates = [] g.finalStates.append(j) g.transitions.append( Transition(g.initialState, '\u03b5', g.finalStates[0])) graph_stack.append(g) # Si elif c == '+': print("3-", c) print(len(graph_stack)) g1 = graph_stack.pop() g2 = graph_stack.pop() g = Graph() g.states = list(set().union(g1.states, g2.states)) # g.states = [state for state in g1.states if state not in g.states] # g.states = [state for state in g2.states if state not in g.states] g.alphabet = list(set().union(g1.alphabet, g2.alphabet)) # g.alphabet = [c for c in g1.alphabet if c not in g.alphabet] # g.alphabet = [c for c in g2.alphabet if c not in g.alphabet] for node in g1.transitions: g.transitions.append(node) for node in g2.transitions: g.transitions.append(node) i = gen_state(states) # générer l'état initial g.states.append(i) states.append(i) g.transitions.append(Transition(i, '\u03b5', g1.initialState)) g.transitions.append(Transition(i, '\u03b5', g2.initialState)) g.initialState = i j = gen_state(states) # générer l'état final g.states.append(j) states.append(j) g.transitions.append(Transition(g1.finalStates[0], '\u03b5', j)) g.transitions.append(Transition(g2.finalStates[0], '\u03b5', j)) g.finalStates = [] g.finalStates.append(j) graph_stack.append(g) # si elif c == '.': print("4-", c) print(len(graph_stack)) g1 = graph_stack.pop() g2 = graph_stack.pop() g = Graph() g.transitions = [node for node in g2.transitions] g.alphabet = list(set().union(g1.alphabet, g2.alphabet)) g.states = [ state for state in g1.states if state not in g.states and state != g1.initialState ] g.states = list(set().union(g.states, g2.states)) g.initialState = g2.initialState g.finalStates.append(g1.finalStates[0]) for node in g1.transitions: if node.mFrom != g1.initialState: g.transitions.append(node) else: g.transitions.append( Transition(g2.finalStates[0], node.mValue, node.mGoto)) graph_stack.append(g) thompson_graph = graph_stack.pop() return thompson_graph
def minimisation(graph): """Fonction de minimisation d'un automate. Algorithme calculant un automate déterministe minimal équivalent au premier. """ print("min") final_states = graph.getFinalStates() states = graph.getStates() alphabet = graph.getAlphabet() partitions = [[], []] # Créer la partition initiale P0 = { {état finaux}, {états non finaux} } for state in states: if state in final_states: partitions[0].append(state) else: partitions[1].append(state) print(partitions) i = 0 while (i < len(partitions)): # Récupérer les pairs des éléments de la partition pairs = list(combinations(partitions[i], 2)) distinguishable = False for p in pairs: if distinguishable: break for letter in alphabet: # Récupérer les transitions possibles depuis la paire d'états avec la lettre t1 = graph.getStateTransitionsLetter(p[0], letter) t2 = graph.getStateTransitionsLetter(p[1], letter) if (len(t1) == 0 or len(t2) == 0): distinguishable = False elif (len(t1) != 0 and len(t2) == 0): x = -1 for j in range(len(partitions)): if (t1[0].mGoto in partitions[j]): x = j distinguishable = True partitions[i].remove(p[0]) partitions.append(list(p[0])) elif (len(t1) == 0 and len(t2) != 0): x = -1 for j in range(len(partitions)): if (t2[0].mGoto in partitions[j]): x = j distinguishable = True partitions[i].remove(p[1]) partitions.append(list(p[1])) else: x = -1 y = -1 for j in range(len(partitions)): if (t1[0].mGoto in partitions[j]): x = j if (t2[0].mGoto in partitions[j]): y = j # Si les états d'arrivée des 2 noeuds sont dans 2 partitions différentes # Alors séparer les états dans la liste des partitions* if x != -1 and y != -1 and x != y: distinguishable = True print(partitions, ' || ', p[1], ' || ', i) partitions[i].remove(p[1]) partitions.append(list(p[1])) # Révenir au début de la liste des partitions car changement i = 0 break else: distinguishable = False i = i + 1 print(partitions) # Construire le graphe minimal graph_min = Graph() graph_min.alphabet = alphabet for p in range(len(partitions)): graph_min.states.append(str(p+1)) for fs in graph.finalStates: if fs in partitions[p]: graph_min.finalStates.append(str(p+1)) break for state in graph.states: for i in range(len(partitions)): # Groupe de l'état source if state in partitions[i]: x = i break trans = graph.getStateTransitions(state) for tr in trans: # Groupe de l'état destination for j in range(len(partitions)): if tr.mGoto in partitions[j]: y = j break # Nouvelle transition entre deux groupes dans l'automate minimal new = Transition(str(x + 1), tr.mValue, str(y + 1)) if new not in graph_min.transitions: graph_min.transitions.append(new) for i in range(len(partitions)): if graph.initialState in partitions[i]: k = i break graph_min.initialState = str(k + 1) return graph_min