Как написать интерпретатор машины тьюринга на питоне

9. Turing Machine in Python

By Bernd Klein. Last modified: 07 Nov 2021.

Just to let you know straight-away: The Turing machine is not a machine. It is a mathematical model, which was formulated by the English mathematician Alan Turing in 1936. It’s a very simple model of a computer, yet it has the complete computing capability of a general purpose computer. The Turing machine (TM) serves two needs in theoretical computer science:

A Turing machine consists only of a few components: A tape on which data can be sequentially stored. The tape consists of fields, which are sequentially arranged. Each field can contain a character of a finite alphabet. This tape has no limits, it goes on infinitely in both directions. In a real machine, the tape would have to be large enough to contain all the data for the algorithm. A TM also contains a head moving in both directions over the tape. This head can read and write one character from the field over which the head resides. The Turing machine is at every moment in a certain state, one of a finite number of states. A Turing program is a list of transitions, which determine for a given state and character («under» the head) a new state, a character which has to be written into the field under the head and a movement direction for the head, i.e. either left, right or static (motionless).

Formal Definition of a Turing machine

A deterministic Turing machine can be defined as a 7-tuple

Example: Binary Complement function

Let’s define a Turing machine, which complements a binary input on the tape, i.e. an input «1100111» e.g. will be turned into «0011000».
Σ = <0, 1>
Q =
q 0 = init
q f = final

Function DefinitionDescription
δ(init,0) = (init, 1, R)If the machine is in state «init» and a 0 is read by the head, a 1 will be written, the state will change to «init» (so actually, it will not change) and the head will be moved one field to the right.
δ(init,1) = (init, 0, R)If the machine is in state «init» and a 1 is read by the head, a 0 will be written, the state will change to «init» (so actually, it will not change) and the head will be moved one field to the right.
δ(init,b) = (final, b, N)If a blank («b»), defining the end of the input string, is read, the TM reaches the final state «final» and halts.

Implementation of a Turing machine in Python

We implement a Turing Machine in Python as a class. We define another class for the read/write tape of the Turing Machine. The core of the tape inside the class Tape is a dictionary, which contains the entries of the tape. This way, we can have negative indices. A Python list is not a convenient data structure, because Python lists are bounded on one side, i.e. bounded by 0.

We define the method str(self) for the class Tape. str(self) is called by the built-in str() function. The print function uses also the str function to calculate the «informal» string representation of an object, in our case the tape of the TM. The method get_tape() of our class TuringMachine makes use of the str representation returned by str.

Источник

Как написать интерпретатор машины тьюринга на питоне

Emulator of turing machine and markov algorithm.

Установка программы производится через пакетный менеджер pip. Получить последнюю версию можно командой (попробуйте добавить sudo в начало команды, если установка не проходит успешно):

После этого программа переходит в режим считывания и на каждую введенную строку печатает результат работы алгоритма. Если программа перестала отвечать на запросы, вероятнее всего, алгоритм зациклился на введенной строке. Нажмите ctrl+C для остановки выполнения.

Ограничения: в НАМ пробельные символы игнорируются, МТ не работает для пустых строчек.

Также программа может работать в режиме компилятора и перерабатывать формальное описание алгоритма в программу на Python.

Скомпилированный файл преобразовывает каждую строчку со входного потока и выдает результат в выходной. Если алгоритм не применим (не останавливается) к данной строчке, то вторая команда будет выполняться вечно или упадет с ошибкой.

Взаимодействие с системой ejudge

Для установки в систему ejudge:

Краткие теоретические сведения

Машина Тьюринга (МТ) — абстрактный исполнитель (абстрактная вычислительная машина). Была предложена Аланом Тьюрингом в 1936 году для формализации понятия алгоритма.

Машина Тьюринга, согласно тезису Чёрча — Тьюринга, способна имитировать все исполнители (с помощью задания правил перехода), каким-либо образом реализующие процесс пошагового вычисления, в котором каждый шаг вычисления достаточно элементарен.

В состав машины Тьюринга входит неограниченная в обе стороны лента, разделённая на ячейки, и управляющее устройство (также называется головкой записи-чтения (ГЗЧ)), способное находиться в одном из множества состояний. Число возможных состояний управляющего устройства конечно и точно задано.

Управляющее устройство может перемещаться влево и вправо по ленте, читать и записывать в ячейки символы некоторого конечного алфавита. Выделяется особый пустой символ, заполняющий все клетки ленты, кроме тех из них (конечного числа), на которых записаны входные данные.

Управляющее устройство работает согласно правилам перехода, которые представляют алгоритм, реализуемый данной машиной Тьюринга. Каждое правило перехода предписывает машине, в зависимости от текущего состояния и наблюдаемого в текущей клетке символа, записать в эту клетку новый символ, перейти в новое состояние и переместиться на одну клетку влево или вправо. Одно из состояний машины Тьюринга помечено как заключительное, и переход в него означает конец работы, остановку алгоритма.

Для каждой возможной конфигурации q[i],a[j] имеется ровно одно правило. Правил нет только для заключительного состояния, попав в которое машина останавливается. Кроме того, необходимо указать конечное и начальное состояния, начальную конфигурацию на ленте и расположение головки машины.

В начале МТ ищет правую границу входного слова, а затем пишет a в пустую ячейку и останавливается.

Источник

Русские Блоги

[Перевод] Написать виртуальный интерпретатор машины с помощью Python

Обновление: у меня небольшое изменение кода в соответствии с комментариями всех. Благодаря Robin-GVX, BS4H и Dagur, конкретный кодздесь

Сама стека машины не имеет никаких регистров, которые помещают все значения, которые необходимо обрабатывать в стек, а затем процессы. Хотя Stack машина проста, но очень мощные, это также причина, почему это виртуальная машина для Бога Python, Java, Postscript, Forth и других языков.

Во-первых, давайте поговорим о стеке. Нам нужна стек указателя инструкций, чтобы сохранить адрес возврата. Это будет иметь возможность вернуться к нам, чтобы начать звонить, когда вызов подпрограммы (например, вызов функции). Мы можем использовать самоможенную код (self-modifying code) Сделать это, просто в Дональде КнутMIX Что сделано. Но если вы сделаете это, вы должны поддерживать свой стек, чтобы убедиться, что ваша рука работает должным образом. В этой статье я действительно не реализую вызов подпрограммы, но это не сложно добиться этого (вы можете рассмотреть реализацию его как упражнения).

После того, как у вас есть стек, вы сэкономите много вещей. Например, рассмотрим такое выражение (2+3)*4 Отказ В Stack Machine Код эквивалентен этому выражению 2 3 + 4 * Отказ Прежде всего, 2 Сумма 3 Нажмите в стек, следующая вещь является оператором + В это время позвольте стек всплывать на два значения, а затем повторно в стеке после результата двух дополнений. Затем 4 В ворсу, затем позвольте стек воспроизвести два значения, а затем восстановить результаты после умножения их. Насколько просто!

Давайте начнем написать простой класс стека. Пусть этот класс наследует collections.deque :

Теперь у нас есть push 、 pop Сумма top Эти три метода. top Метод используется для просмотра верхних элементов стека.

Нам также нужен указатель инструкции, чтобы указать на код, который будет выполнен в программе.

В это время мы добавляем некоторые из простых в использовании функций для сохранения нескольких ударов на клавиатуре.

Тогда мы добавляем один dispatch Функции, чтобы завершить все, что делает каждый код операции (мы не реальны с помощью кода оператора, просто динамично расширить его, вы знаете). Сначала добавьте интерпретатор в петлю:

Как вы можете видеть, этот товар должен сделать одну вещь, то есть, получить следующую команду, так что указатель команд индуцируется, а затем обрабатывается отдельно в соответствии с кодом операции. dispatch Код функции немного длиннее.

В основном, этот код только на основе кода поиска работы, например, * Корреспонденция self.mul , drop Корреспонденция self.drop , dup Корреспонденция self.dup Отказ Кстати, этот код вы видите здесь по своей сути простая версия. Forth Отказ А также Forth Язык все еще стоит увидеть.

Короче, это один, но я обнаружил, что OPCode * Если вы называете это напрямую self.mul И выполнить это. Именно так:

В настоящее время, поздравление, виртуальная машина будет завершено.

Зададим несколько операций, а затем использовать наши только законченные виртуальные машины иp-code Язык для написания программы.

Напишем один с нашей виртуальной машиной print((2+3)*4) Пример эквивалентного эффекта.

Вы можете попробовать запустить его.

Теперь введите новую операцию jump Т.е. go-to Эксплуатация

Это меняет только значение указателя инструкций. Давайте посмотрим, как делает прыжок филиала.

Это также очень просто. Если вы хотите добавить промежуток времени, вам нужно только сделать простое выполнение test-value true-value false-value IF JMP Да, (обработка Филиала является очень распространенной операцией, многие виртуальные машины обеспечивают аналогичные JNE Такая операция. JNE Быть jump if not equal Сокращенное название).

Следующая программа требует от пользователя ввести два числа, а затем распечатать их сумму и произведение.

over 、 read Сумма cast_int Эти три операции капли, как это:

Следующая программа требует, чтобы пользователь ввести номер, затем печать этого номера нечетное или даже.

Есть небольшая практика здесь, чтобы реализовать это: увеличение call Сумма return Эти два опкода. call OPCode сделает следующее: нажмите текущий адрес в возвратный стек, а затем вызовите self.jmp() 。 return Код операции выполнит следующие вещи: выпрыгнул возвратный стек, выскочил из значения элемента, дает указатель инструкции (это значение позволяет прыгать назад или из call Вернитесь в звонок). Когда вы выполняете эти две команды, то ваша виртуальная машина может вызвать подпрограмму.

Простой парсер

Создайте небольшой язык, который имитирует вышеуказанные программы. Мы будем скомпилировать его в наш машинный код.

Простая оптимизация: постоянная складка

Постоянная складная (Constant folding) Это обнаружение глазок (peephole optimizationПример этого, то есть, это необходимо сделать некоторую предварительно подсчетную работу для некоторых очевидных фрагментов кода во время компиляции. Например, для математических выражений, связанных с постоянными, например, 2 3 + Эта оптимизация может быть легко достигнута.

Если вы реализованы Forth words То есть функция, вы можете сделать дополнительную оптимизацию, например, удаление программного кода, который может никогда не использоваться (dead code elimination)

Мы можем создать простой Perl, как это

Проверьте наш REPL с некоторыми простыми программами

Следующий шаг

При добавлении его call Сумма return После этого, вы можете позволить пользователю определить свои собственные функции. ВForth Функция называется словом, и они начинают начинать с двоеточием, а затем заканчиваться точкой с запятой. Например, целое квадрат слово долго капает

На самом деле, вы можете попробовать этот пункт в программе, такие как GForth

Вы можете найти его в синтаксический анализатор : Для поддержки этого. После того, как вы нашли двоеточие, вы должны записать его имя и адрес (например: в программе) и вставить их в таблицу символов (symbol table)середина. Просто, вы можете даже поставить код целой функции (включая точку с запятой) в словаре, такие как:

Когда вы завершили разбор работы, вы можетеСвязьВаша программа: траверс весь мастер и искать пользовательские функции в таблице символов. После того, как вы найдете один и он не появляется позади основной программы, то вы можете прикрепить его к основной программе. Затем call Заменять square Здесь Является ли адрес вставляется в функции.

Для того, чтобы гарантировать, что программа может быть реализована, как правило, следует рассмотреть возможность исключения jmp Операция. В противном случае, вы должны решить их. Это выполнить, но вы должны сохранить их в порядке написания программ пользователя. Например, вы хотите, чтобы перемещаться между подпрограммами, вы должны быть дополнительный уход. Вы можете добавить exit Функция используется для остановки программы (возможно, потребуется указать возвращаемое значение операционной системы), так что основная программа будет продолжать работать в подпрограмме.

На самом деле, хорошая планировка космонавтики может относиться к основной программе в качестве имени. main Sub рутина. Или то, что вы решили будет.

Как вы можете видеть, это очень интересно, и в ходе этого процесса, вы узнали много знаний о генерации кода, ссылки, макет программы пространства.

Другие вещи, которые вы можете сделать

Вы можете использовать байткод Python для создания библиотеки, чтобы попытаться сделать виртуальный машинный код, как родной байткод Python. Или использовать Java для запуска в JVM выше, так что вы можете использовать свободное использованиеJITing。

Кроме того, вы также можете попробоватьregister machineОтказ Вы можете попробовать использовать фрейм стека (stack framesРеализация стека вызовов (call stack), На основе этого установить телефонную сессию.

Я уже во мне.C++ stack machine Для достижения этих вещей, вы можете обратиться к нему.

Я уже сделал код, представленный здесь.CrianzaОн использует больше оптимизации и экспериментальные модели для компиляции программы в байт-код Python.

Полный код

Вот весь код, совместимый с Python 2 и Python 3

Вы можете передатьздесь Понятно.

эта статьяOneAPM Инженеры скомпилированы. Хотите прочитать дополнительные технические статьи, пожалуйста, посетите INEAPMОфициальный технологический блог。

Источник

Доказательство Тьюринг-полноты однострочников на Python

Немного теории

Чёткие правила данного автомата изложены в Википедии по ссылке здесь.

Вкратце, мы имеем бесконечную ленту из последовательно размещённых клеток, которые могут иметь только два состояния (0 и 1), будущее состояние клетки зависит от текущих значений трёх клеток — её самой и двух её ближайших соседей и рассчитывается по определённому несложному алгоритму.

Получается, что если мы сможем написать в одну строчку этот клеточный автомат, значит и любой другой алгоритм написать в одну строчку тоже будет возможно.

Реализация

Сразу уточню, что символ «;» я считал началом новой строки, чем он по сути и является, иначе задача превращается в тривиальную.

Итак, опредилившись с тем что же именно я собираюсь написать, я, недолго думая, запустил VSCode и. И завис. Потому что неясно было что писать. Ясно было, что нужен цикл while, ввод начального состояния, которое нужно как-то обработать, действия над ним в цикле, Кроме того, цикл надо ещё как-то остановливать, если состояние системы стабилизировалось и больше не меняется.

Как это всё уместить в одну строчку, было не очень понятно. Например даже результат вызова input() нельзя никак занести в обычную в переменную и потом работать с ним дальше одной строкой.

Итоговый код и как он работает

Итак, нам необходимо каждый проход цикла проверять состояние системы и заканчивать выполнение программы, если оно такое же, как предыдущее(состояние стабилизировалось).

Сперва, мы должны запросить на вход начальное состояние, причем сделать это лишь один раз. Также мы будем сравнивать текущее состояние системы с предыдущим. Для этого используем следующий код:

Далее, уже в теле цикла мы объявляем фиктивную переменную a которой присваиваем значение длинного длинного сравнения через оператор or. На самом деле, оператор сравнения здесь нужен чтобы выполнить большое количество исполняемого кода, в котром каждая вызываемая функция вернёт None. Возможно, можно было реализовать подобное более красиво, но это самое быстрое рабочее решение, которое пришло мне в голову.

В полном же варианте нарощенном на данный скелет мы обновляем l (предыдущее состояние), проходим один цикл клеточного автомата, перезаписывая переменную s, и выводим новое состояние.

Вот так выглядит финальный код.

Правда, скорее всего, код получится слегка нечитаемым да и дебаггинг будет затруднён. )

Автор знаком с python на любительском уровне и не пишет на нём ничего серьёзного, поэтому прошу простить, если проглядел какие-то очевидные вещи и возможности. Автор понимает, что написание подобного кода в реальном проекте, чревато некоторым непониманием со стороны коллег и не призывает никого повторять изложенные здесь эксперименты)

Источник

sandipanweb

Simply Data Science

Simulating a Turing Machine with Python and executing programs on it

In this article, we shall implement a basic version of a Turing Machine in python and write a few simple programs to execute them on the Turing machine. This article is inspired by the edX / MITx course Paradox and Infinity and few of the programs to be executed on the (simulated) Turing machine are taken from the course. Also, some programs are from this Cambridge tutorial.

A few Definitions

Let’s start by defining a Turing machine (originally invented by Alan Turing) formally, as is shown in the following figure:

Как написать интерпретатор машины тьюринга на питоне

The python implementation for simulating a Turing Machine

The following python code shows a very simple implementation of a Turing machine. It accepts a program as a string, with each transition function defined on a new line. The state halt is denoted by H.

In the next section we shall show how a program on this Turing Machine will look like and how to run such a program, by instantiating the above class. We shall demonstrate with a few programs.

1. Binary Addition with Turing Machine

The following figure shows how to perform binary addition with a Turing machine, where the binary numbers to be added are input to the Turing machine and are separated by a single blank. The TM header is assumed to be positioned at the leftmost position of the first number, in the very beginning.

Как написать интерпретатор машины тьюринга на питоне

0 0 0 r 0
0 1 1 r 0
0 _ _ r 1
1 0 0 r 1
1 1 1 r 1
1 _ _ l 2
2 0 1 l 2
2 1 0 l 3
2 _ _ r 5
3 0 0 l 3
3 1 1 l 3
3 _ _ l 4
4 0 1 r 0
4 1 0 l 4
4 _ 1 r 0
5 1 _ r 5
5 _ _ * H

Given the two binary numbers, the Turing Machine

till the second number becomes 0.

The following code shows how the above program can be run to add two input binary numbers 1101 (decimal 13) and 101 (decimal 5) to output the binary number 10010 (decimal 18). The final state of the machine is H (halt), as expected.

The following animation shows how the binary numbers are added using the TM simulator.

Как написать интерпретатор машины тьюринга на питоне

2. Converting a Binary to a Unary number with TM

Let’s assume the TM tape contains a binary representation of a number n ( n > 0 ) as a sequence of zeros and ones, and is otherwise blank. The reader positioned at the left-most member of the sequence. The following figure shows the program that replaces the original sequence with a sequence of n ones, where the original sequence names n in binary notation:

Как написать интерпретатор машины тьюринга на питоне
The following animation shows the result of running the program on the TM simulator, with the input 1010, the output obtained is a sequence of 10 ones.

Как написать интерпретатор машины тьюринга на питоне

3. Converting a Unary to a Binary number with TM


Let’s assume the TM tape contains a sequence of n ones ( n > 0 ) and is otherwise blank. The reader positioned at the left-most member of the sequence. The following TM program replaces the sequence of n ones, with a sequence of zeroes and ones that names n in binary notation:

Как написать интерпретатор машины тьюринга на питоне

The following animation shows the result of running the program on the TM simulator, with the input 11111111111 (eleven ones), the output obtained is the binary representation of 11.

Как написать интерпретатор машины тьюринга на питоне

4. Doubling the length of a sequence with TM


The following figure shows the program to be run to double the length of a sequence of ones, input to the TM

Как написать интерпретатор машины тьюринга на питоне

The following animation shows the result of running the program on the TM simulator, starting with five ones as input, obtaining ten ones on the tape as output.

Как написать интерпретатор машины тьюринга на питоне

5. Simulating the 4-state Busy Beaver with TM


The following figure shows the program to be run

Как написать интерпретатор машины тьюринга на питоне

The following animation shows the result of running the program on the TM simulator, as expected it outputs 13 ones on the tapes and halts in 107 steps.
Как написать интерпретатор машины тьюринга на питоне

6. Detecting a Palindrome with TM

The following program checks a string of symbols on the tape and returns a 1 if it is a palindrome and a 0 if it is not.

Как написать интерпретатор машины тьюринга на питоне

The following animation shows the result of running the program on the TM simulator with a palindrome.

Как написать интерпретатор машины тьюринга на питоне

The following animation shows the result of running the program on the TM simulator with a non-palindrome.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *