def nfa_dot_importer(input_file: str) -> dict:
    """ Imports a NFA from a DOT file.

    Of .dot files are recognized the following attributes
      • nodeX   shape=doublecircle -> accepting node;
      • nodeX   root=true -> initial node;
      • edgeX   label="a" -> action in alphabet;
      • fakeX    style=invisible -> dummy invisible nodes pointing
                to initial state (it will be skipped);
      • fakeX->S [style=bold] -> dummy transitions to draw arrows
                pointing to initial states (they will be skipped).

    All invisible nodes are skipped.

    Forbidden names:
      • 'fake'  used for graphical purpose to drawn the arrow of
        the initial state
      • 'sink'  used as additional state when completing a NFA

    Forbidden characters:
      • "
      • '
      • (
      • )
      • spaces

    :param str input_file: Path to input DOT file;
    :return: *(dict)* representing a NFA.
    """

    # pyDot Object
    g = pydot.graph_from_dot_file(input_file)[0]

    states = set()
    initial_states = set()
    accepting_states = set()

    replacements = {'"': '', "'": '', '(': '', ')': '', ' ': ''}

    for node in g.get_nodes():
        attributes = node.get_attributes()
        if node.get_name() == 'fake' \
                or node.get_name() == 'None' \
                or node.get_name() == 'graph' \
                or node.get_name() == 'node':
            continue
        if 'style' in attributes \
                and attributes['style'] == 'invisible':
            continue

        node_reference = __replace_all(replacements,
                                       node.get_name()).split(',')
        if len(node_reference) > 1:
            node_reference = tuple(node_reference)
        else:
            node_reference = node_reference[0]
        states.add(node_reference)
        for attribute in attributes:
            if attribute == 'root':
                initial_states.add(node_reference)
            if attribute == 'shape' \
                    and attributes['shape'] == 'doublecircle':
                accepting_states.add(node_reference)

    alphabet = set()
    transitions = {}
    for edge in g.get_edges():
        source = __replace_all(replacements,
                               edge.get_source()).split(',')
        if len(source) > 1:
            source = tuple(source)
        else:
            source = source[0]
        destination = __replace_all(replacements,
                                    edge.get_destination()).split(',')
        if len(destination) > 1:
            destination = tuple(destination)
        else:
            destination = destination[0]

        if source not in states or destination not in states:
            continue

        label = __replace_all(replacements, edge.get_label())
        alphabet.add(label)

        transitions.setdefault((source, label), set()).add(
            destination)

    nfa = {
        'alphabet': alphabet,
        'states': states,
        'initial_states': initial_states,
        'accepting_states': accepting_states,
        'transitions': transitions
    }

    return nfa
def nfa_dot_importer ( input_file : str ) -> dict : g = pydot . graph_from_dot_file ( input_file ) [ 0 ] states = set ( ) initial_states = set ( ) accepting_states = set ( ) replacements = { '"' : '' , "'" : '' , '(' : '' , ')' : '' , ' ' : '' } for node in g . get_nodes ( ) : attributes = node . get_attributes ( ) if node . get_name ( ) == 'fake' or node . get_name ( ) == 'None' or node . get_name ( ) == 'graph' or node . get_name ( ) == 'node' : continue if 'style' in attributes and attributes [ 'style' ] == 'invisible' : continue node_reference = __replace_all ( replacements , node . get_name ( ) ) . split ( ',' ) if len ( node_reference ) > 1 : node_reference = tuple ( node_reference ) else : node_reference = node_reference [ 0 ] states . add ( node_reference ) for attribute in attributes : if attribute == 'root' : initial_states . add ( node_reference ) if attribute == 'shape' and attributes [ 'shape' ] == 'doublecircle' : accepting_states . add ( node_reference ) alphabet = set ( ) transitions = { } for edge in g . get_edges ( ) : source = __replace_all ( replacements , edge . get_source ( ) ) . split ( ',' ) if len ( source ) > 1 : source = tuple ( source ) else : source = source [ 0 ] destination = __replace_all ( replacements , edge . get_destination ( ) ) . split ( ',' ) if len ( destination ) > 1 : destination = tuple ( destination ) else : destination = destination [ 0 ] if source not in states or destination not in states : continue label = __replace_all ( replacements , edge . get_label ( ) ) alphabet . add ( label ) transitions . setdefault ( ( source , label ) , set ( ) ) . add ( destination ) nfa = { 'alphabet' : alphabet , 'states' : states , 'initial_states' : initial_states , 'accepting_states' : accepting_states , 'transitions' : transitions } return nfa
Imports a NFA from a DOT file.

    Of .dot files are recognized the following attributes
      • nodeX   shape=doublecircle -> accepting node;
      • nodeX   root=true -> initial node;
      • edgeX   label="a" -> action in alphabet;
      • fakeX    style=invisible -> dummy invisible nodes pointing
                to initial state (it will be skipped);
      • fakeX->S [style=bold] -> dummy transitions to draw arrows
                pointing to initial states (they will be skipped).

    All invisible nodes are skipped.

    Forbidden names:
      • 'fake'  used for graphical purpose to drawn the arrow of
        the initial state
      • 'sink'  used as additional state when completing a NFA

    Forbidden characters:
      • "
      • '
      • (
      • )
      • spaces

    :param str input_file: Path to input DOT file;
    :return: *(dict)* representing a NFA.