Ejemplo n.º 1
0
 def _get_next_configuration(self, old_config):
     """Advance to the next configuration."""
     transitions = set()
     if old_config.remaining_input:
         transitions.add(
             self._get_transition(old_config.state,
                                  old_config.remaining_input[0],
                                  old_config.stack.top()))
     transitions.add(
         self._get_transition(old_config.state, '', old_config.stack.top()))
     if None in transitions:
         transitions.remove(None)
     if len(transitions) == 0:
         raise exceptions.RejectionException(
             'The automaton entered a configuration for which no '
             'transition is defined ({}, {}, {})'.format(
                 old_config.state, old_config.remaining_input[0],
                 old_config.stack.top()))
     if len(transitions) > 1:
         raise pda_exceptions.NondeterminismError(
             'The automaton entered a configuration for which more'
             'than one transition is defined ({}, {}'.format(
                 old_config.state, old_config.stack.top()))
     input_symbol, new_state, new_stack_top = transitions.pop()
     remaining_input = old_config.remaining_input
     if input_symbol:
         remaining_input = remaining_input[1:]
     new_config = PDAConfiguration(
         new_state, remaining_input,
         self._replace_stack_top(old_config.stack, new_stack_top))
     return new_config
Ejemplo n.º 2
0
 def _check_for_input_rejection(self, current_state, stack):
     """Raise an error if the given config indicates rejected input."""
     # If current state is not a final state and stack is not empty
     if current_state not in self.final_states and stack:
         raise exceptions.RejectionException(
             'the DPDA stopped in a non-accepting configuration '
             '({}, {})'.format(current_state, stack))
Ejemplo n.º 3
0
    def read_input_stepwise(self, input_str):
        """
        Check if the given string is accepted by this Turing machine.

        Yield the current configurations of the machine at each step.
        """
        current_configurations = {
            TMConfiguration(self.initial_state,
                            TMTape(input_str, blank_symbol=self.blank_symbol))
        }
        yield current_configurations

        # The initial state cannot be a final state for a NTM, so the first
        # iteration is always guaranteed to run (as it should)
        while current_configurations:
            new_configurations = set()
            for config in current_configurations:
                if self._has_accepted(config):
                    # One accepting configuration is enough.
                    return
                new_configurations.update(
                    self._get_next_configurations(config))
            current_configurations = new_configurations
            yield current_configurations

        raise exceptions.RejectionException(
            'the NTM did not reach an accepting configuration')
Ejemplo n.º 4
0
    def read_input_stepwise(self, input_str):
        """
        Check if the given string is accepted by this NPDA.

        Yield the NPDA's current configurations at each step.
        """
        current_configurations = set()
        current_configurations.add(
            PDAConfiguration(self.initial_state, input_str,
                             PDAStack([self.initial_stack_symbol])))

        yield current_configurations

        while current_configurations:
            new_configurations = set()
            for config in current_configurations:
                if self._has_accepted(config):
                    # One accepting configuration is enough.
                    return
                if config.remaining_input:
                    new_configurations.update(
                        self._get_next_configurations(config))
                elif self._has_lambda_transition(config.state,
                                                 config.stack.top()):
                    new_configurations.update(
                        self._get_next_configurations(config))
            current_configurations = new_configurations
            yield current_configurations

        raise exceptions.RejectionException(
            'the NPDA did not reach an accepting configuration')
Ejemplo n.º 5
0
    def read_input_stepwise(self, input_str):
        """Checks if the given string is accepted by this Turing machine,
        using a BFS of every possible configuration from each configuration.
        Yields the current configuration of the machine at each step.
        """
        self._restart_configuration(input_str)
        queue = deque([self])
        while len(queue) > 0:
            current_tm = queue.popleft()
            yield {MTMConfiguration(self.current_state, tuple(self.tapes))}

            possible_transitions = current_tm._get_transition()
            if possible_transitions is None:
                if current_tm._has_accepted():
                    return {
                        MTMConfiguration(self.current_state, tuple(self.tapes))
                    }
            else:
                for transition in possible_transitions[1:]:
                    queue.append(
                        current_tm.copy()._get_next_configuration(transition))

                queue.append(
                    current_tm._get_next_configuration(
                        possible_transitions[0]))

        raise exceptions.RejectionException(
            'the multitape MNTM did not reach an accepting configuration')
Ejemplo n.º 6
0
 def _get_transition(self, state, tape_symbol):
     """Get the transiton tuple for the given state and tape symbol."""
     if (state in self.transitions
             and tape_symbol in self.transitions[state]):
         return self.transitions[state][tape_symbol]
     else:
         raise exceptions.RejectionException(
             'The machine entered a non-final configuration for which no '
             'transition is defined ({}, {})'.format(state, tape_symbol))
Ejemplo n.º 7
0
    def _get_next_current_state(self, current_state, input_symbol):
        """
        Follow the transition for the given input symbol on the current state.

        Raise an error if the transition does not exist.
        """
        if input_symbol in self.transitions[current_state]:
            return self.transitions[current_state][input_symbol]
        else:
            raise exceptions.RejectionException(
                '{} is not a valid input symbol'.format(input_symbol))
Ejemplo n.º 8
0
 def _get_transition(self, state, input_symbol, stack_symbol):
     """Get the transiton tuple for the given state and symbols."""
     if (state in self.transitions
             and input_symbol in self.transitions[state]
             and stack_symbol in self.transitions[state][input_symbol]):
         return self.transitions[state][input_symbol][stack_symbol]
     else:
         raise exceptions.RejectionException(
             'The automaton entered a configuration for which no '
             'transition is defined ({}, {}, {})'.format(
                 state, input_symbol, stack_symbol))
Ejemplo n.º 9
0
 def _get_next_configuration(self, old_config):
     """Advance to the next configuration."""
     transitions = {
         self._get_transition(old_config.state,
                              old_config.tape.read_symbol())
     }
     if None in transitions:
         transitions.remove(None)
     if len(transitions) == 0:
         raise exceptions.RejectionException(
             'The machine entered a non-final configuration for which no '
             'transition is defined ({}, {})'.format(
                 old_config.state, old_config.tape.read_symbol()))
     tape = old_config.tape
     (new_state, new_tape_symbol, direction) = transitions.pop()
     tape = tape.write_symbol(new_tape_symbol)
     tape = tape.move(direction)
     return TMConfiguration(new_state, tape)
Ejemplo n.º 10
0
 def _check_for_input_rejection(self, current_state):
     """Raise an error if the given config indicates rejected input."""
     if current_state not in self.final_states:
         raise exceptions.RejectionException(
             'the DFA stopped on a non-final state ({})'.format(
                 current_state))
Ejemplo n.º 11
0
 def _check_for_input_rejection(self, current_states):
     """Raise an error if the given config indicates rejected input."""
     if not (current_states & self.final_states):
         raise exceptions.RejectionException(
             'the NFA stopped on all non-final states ({})'.format(
                 ', '.join(current_states)))
Ejemplo n.º 12
0
 def _check_for_input_rejection(self, current_configuration):
     """Raise an error if the given config indicates rejected input."""
     if not self._has_accepted(current_configuration):
         raise exceptions.RejectionException(
             'the DPDA stopped in a non-accepting configuration '
             '({state}, {stack})'.format(**current_configuration._asdict()))
Ejemplo n.º 13
0
    def read_input_as_ntm(self, input_str):
        """Simulates the machine as a single-tape Turing machine.
        Yields the configuration at each step."""
        self._restart_configuration(input_str)
        head_symbol = '^'
        tape_separator_symbol = '_'
        extended_tape = ''
        tapes_copy = self.tapes.copy()
        for tape_copy in tapes_copy:
            tape_str = tape_copy.get_symbols_as_str()
            extended_tape += tape_str[0] + head_symbol + \
                tape_str[1:] + tape_separator_symbol

        current_state = self.initial_state
        yield {
            TMConfiguration(
                current_state,
                TMTape(extended_tape,
                       blank_symbol=self.blank_symbol,
                       current_position=0))
        }

        # If the machine has not reached an accepting state.
        while current_state not in self.final_states:
            i = 0  # current position
            virtual_heads = self._read_extended_tape(extended_tape,
                                                     head_symbol,
                                                     tape_separator_symbol)
            try:
                next_config = self.transitions[current_state][virtual_heads]
            except KeyError:
                raise exceptions.RejectionException(
                    'the multitape NTM did not reach an accepting '
                    'configuration')
            next_state, moves = next_config[0]
            for move in moves:
                new_head, direction = move
                executing_changes = True

                while executing_changes:
                    if extended_tape[i] == head_symbol:
                        # Head has been found (previous symbol is the head).
                        # This replaces the previous symbol with the new_head.
                        extended_tape = (extended_tape[:i - 1] + new_head +
                                         extended_tape[i:])
                        extended_tape = extended_tape[:i] + \
                            '' + extended_tape[i + 1:]

                        # After replacing, the machine must change the
                        # position of the virtual head of the current virtual
                        # tape.
                        if direction == 'R':
                            i += 1
                        elif direction == 'L':
                            i -= 1
                        else:  # direction == 'N'
                            i += 0

                        if extended_tape[i - 1] == tape_separator_symbol:
                            i -= 1
                            extended_tape = extended_tape[:i] + \
                                self.blank_symbol + \
                                head_symbol + extended_tape[i:]

                            i += 1
                        else:
                            extended_tape = (extended_tape[:i] + head_symbol +
                                             extended_tape[i:])

                    elif extended_tape[i] == tape_separator_symbol:
                        executing_changes = False

                    i += 1

            current_state = next_state
            yield {
                TMConfiguration(
                    current_state,
                    TMTape(extended_tape,
                           blank_symbol=self.blank_symbol,
                           current_position=i - 1))
            }