Exemplo n.º 1
0
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
Exemplo n.º 2
0
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