Example #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()
     ])
Example #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,
     )
     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()
         ])
Example #3
0
 def setup(self):
     """Provide a configuration for testing."""
     self.config = TMConfiguration(
         'q2',
         TMTape(
             tape='abcdefghij',
             blank_symbol='.',
             current_position=2,
         )
     )
Example #4
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')
Example #5
0
 def _get_next_configurations(self, old_config):
     """Advance to the next configurations."""
     transitions = self._get_transitions(old_config.state,
                                         old_config.tape.read_symbol())
     new_configs = set()
     for new_state, new_tape_symbol, direction in transitions:
         tape = old_config.tape
         tape = tape.write_symbol(new_tape_symbol)
         tape = tape.move(direction)
         new_configs.add(TMConfiguration(new_state, tape))
     return new_configs
Example #6
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,
            ))
        )
Example #7
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
Example #8
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)
Example #9
0
class TestTMTools(test_tm.TestTM):
    """A test class for testing Turing machine utility functions."""

    def setup(self):
        """Provide a configuration for testing."""
        self.config = TMConfiguration(
            'q2',
            TMTape(
                tape='abcdefghij',
                blank_symbol='.',
                current_position=2,
            )
        )

    def test_repr_config(self):
        """Should return a string representation ot the given configuration."""
        nose.assert_equal(
            repr(self.config),
            'TMConfiguration(\'q2\', TMTape(\'abcdefghij\', 2))'
        )

    def test_print_config(self):
        """Should print the given configuration to stdout."""
        out = io.StringIO()
        with contextlib.redirect_stdout(out):
            self.config.print()
        nose.assert_equal(out.getvalue().rstrip(), '{}: {}\n{}'.format(
            'q2', 'abcdefghij', '^'.rjust(7)))

    @patch('automata.tm.configuration.TMConfiguration.print')
    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()
        ])

    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'))
Example #10
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))
            }