Exemple #1
0
 def test_print_configs(self, print_config):
     """Should print each machine configuration to stdout."""
     tape1 = TMTape(
         tape='01010101',
         blank_symbol='.',
         current_position=0,
     )
     tape2 = TMTape(
         tape='x1010101',
         blank_symbol='.',
         current_position=-1,
     )
     tape3 = TMTape(
         tape='yx1010101',
         blank_symbol='.',
         current_position=-2,
     )
     configs = [
         TMConfiguration(tape1, 'q0'),
         TMConfiguration(tape2, 'q1'),
         TMConfiguration(tape3, 'q2')
     ]
     tmtools.print_configs(configs)
     nose.assert_equal(print_config.call_args_list, [
         call(),
         call(),
         call()
     ])
Exemple #2
0
 def test_print_configs(self, print_config):
     """Should print each machine configuration to stdout."""
     tape1 = TMTape(
         tape='01010101',
         blank_symbol='.',
         current_position=0,
         position_offset=0
     )
     tape2 = TMTape(
         tape='x1010101',
         blank_symbol='.',
         current_position=-1,
         position_offset=0
     )
     tape3 = TMTape(
         tape='yx1010101',
         blank_symbol='.',
         current_position=-2,
         position_offset=1
     )
     tmtools.print_configs([
         ('q0', tape1),
         ('q1', tape2),
         ('q2', tape3)
     ])
     nose.assert_equal(print_config.call_args_list, [
         call('q0', tape1, 1),
         call('q1', tape2, 1),
         call('q2', tape3, 1)
     ])
Exemple #3
0
 def test_print_configs(self, print_config):
     """Should print each machine configuration to stdout."""
     tape1 = TMTape(
         tape='01010101',
         blank_symbol='.',
         current_position=0,
     )
     tape2 = TMTape(
         tape='x1010101',
         blank_symbol='.',
         current_position=-1,
     )
     tape3 = TMTape(
         tape='yx1010101',
         blank_symbol='.',
         current_position=-2,
     )
     configs = [
         TMConfiguration(tape1, 'q0'),
         TMConfiguration(tape2, 'q1'),
         TMConfiguration(tape3, 'q2'),
         MTMConfiguration('q1', (tape1, tape2, tape3))
     ]
     out = io.StringIO()
     with contextlib.redirect_stdout(out):
         tmtools.print_configs(configs)
         self.assertEqual(print_config.call_args_list, [
             call(),
             call(),
             call()
         ])
Exemple #4
0
 def test_get_symbols_as_str(self):
     """Should print tape contents as a string without spaces."""
     tape = TMTape(
         tape='abcdef',
         blank_symbol='.',
         current_position=2,
     )
     self.assertEqual(tape.get_symbols_as_str(), 'abcdef')
Exemple #5
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')
Exemple #6
0
 def test_tape_iteration(self):
     """Should be able to iterate over a Turing machine tape."""
     tape = TMTape(
         tape='abcdef',
         blank_symbol='.',
         current_position=2,
     )
     nose.assert_equal(tuple(tape), ('a', 'b', 'c', 'd', 'e', 'f'))
Exemple #7
0
 def setup(self):
     """Provide a configuration for testing."""
     self.config = TMConfiguration(
         'q2',
         TMTape(
             tape='abcdefghij',
             blank_symbol='.',
             current_position=2,
         )
     )
Exemple #8
0
 def test_print_config(self):
     """Should print the given configuration to stdout."""
     out = io.StringIO()
     with contextlib.redirect_stdout(out):
         tmtools.print_config(
             current_state='q2', tape=TMTape(
                 tape='abcdefghij', blank_symbol='.',
                 current_position=2, position_offset=1),
             max_position_offset=3)
     nose.assert_equal(out.getvalue().rstrip(), '{}: {}\n{}'.format(
         'q2', '..abcdefghij', '^'.rjust(10)))
Exemple #9
0
    def setUp(self):
        """Provide a configuration for testing."""
        self.config = TMConfiguration(
            'q2',
            TMTape(
                tape='abcdefghij',
                blank_symbol='.',
                current_position=2,
            )
        )

        self.config2 = MTMConfiguration(
            'q1', (TMTape(
                tape='abcdefghij',
                blank_symbol='.',
                current_position=2,
            ), TMTape(
                tape='klmnopq',
                blank_symbol='.',
                current_position=5,
            ))
        )
Exemple #10
0
    def read_input_stepwise(self, input_str):
        """
        Check if the given string is accepted by this Turing machine.

        Yield the current configuration of the machine at each step.
        """
        current_configuration = TMConfiguration(
            self.initial_state,
            TMTape(input_str, blank_symbol=self.blank_symbol))
        yield current_configuration

        # The initial state cannot be a final state for a DTM, so the first
        # iteration is always guaranteed to run (as it should)
        while not self._has_accepted(current_configuration):
            current_configuration = self._get_next_configuration(
                current_configuration)
            yield current_configuration
Exemple #11
0
    def __init__(self,
                 *,
                 states,
                 input_symbols,
                 tape_symbols,
                 n_tapes,
                 transitions,
                 initial_state,
                 blank_symbol,
                 final_states,
                 tapes=None,
                 current_state=None):
        """Initialize a complete Turing machine."""
        self.states = states.copy()
        self.input_symbols = input_symbols.copy()
        self.tape_symbols = tape_symbols.copy()
        self.transitions = copy.deepcopy(transitions)
        self.initial_state = initial_state
        self.blank_symbol = blank_symbol
        self.final_states = final_states.copy()
        self.n_tapes = n_tapes

        if tapes is not None:
            self.tapes = [tape.copy() for tape in tapes]
        else:
            self.tapes = [
                TMTape(self.blank_symbol, blank_symbol=self.blank_symbol)
                for _ in range(n_tapes)
            ]

        if current_state is not None:
            self.current_state = current_state
        else:
            self.current_state = self.initial_state

        self.validate()
Exemple #12
0
    def read_input_stepwise(self, input_str):
        """
        Check if the given string is accepted by this Turing machine.

        Yield the current configuration of the machine at each step.
        """
        current_state = self.initial_state
        current_direction = None
        tape = TMTape(input_str, blank_symbol=self.blank_symbol)
        yield current_state, tape

        # The initial state cannot be a final state for a DTM, so the first
        # iteration is always guaranteed to run (as it should)
        while current_state not in self.final_states:

            input_symbol = tape.read_symbol()
            (current_state, new_tape_symbol,
             current_direction) = self._get_transition(current_state,
                                                       input_symbol)
            tape.write_symbol(new_tape_symbol)
            tape.move(current_direction)

            yield current_state, tape
Exemple #13
0
    def _validate_input_yield(self, input_str):
        """
        Check if the given string is accepted by this Turing machine.

        Yield the current configuration of the machine at each step.
        """
        current_state = self.initial_state
        current_direction = None
        tape = TMTape(input_str, blank_symbol=self.blank_symbol)
        yield current_state, tape

        # The initial state cannot be a final state for a DTM, so the first
        # iteration is always guaranteed to run (as it should)
        while current_state not in self.final_states:

            input_symbol = tape.read_symbol()
            (current_state, new_tape_symbol,
                current_direction) = self._get_transition(
                    current_state, input_symbol)
            tape.write_symbol(new_tape_symbol)
            tape.move(current_direction)

            yield current_state, tape
Exemple #14
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))
            }