Счетная машина или счетчик-автомат — это абстрактная машина, используемая в формальной логике и теоретической информатике для моделирования вычислений . Это самый примитивный из четырех типов регистровых машин . Счетная машина состоит из набора из одного или нескольких неограниченных регистров , каждый из которых может содержать одно неотрицательное целое число, и списка (обычно последовательных) арифметических и управляющих инструкций для машины. Счетная машина обычно используется в процессе проектирования параллельных алгоритмов в отношении принципа взаимного исключения. При использовании таким образом счетчик-машина используется для моделирования дискретных временных шагов вычислительной системы в отношении доступа к памяти. Путем моделирования вычислений в отношении доступа к памяти для каждого соответствующего вычислительного шага параллельные алгоритмы могут быть спроектированы таким образом, чтобы избежать взаимоблокировки, одновременной операции записи двумя (или более) потоками по одному и тому же адресу памяти.
Счетные машины с тремя счетчиками могут вычислять любую частично рекурсивную функцию одной переменной. Счетные машины с двумя счетчиками являются полными по Тьюрингу : они могут имитировать любую соответствующим образом закодированную машину Тьюринга, но есть некоторые простые функции, которые они не могут вычислить. Счетные машины только с одним счетчиком могут распознавать надлежащее надмножество регулярных языков и подмножество детерминированных контекстно-свободных языков . [1]
Для данной модели счетчика машин набор инструкций крошечный — от одной до шести или семи инструкций. Большинство моделей содержат несколько арифметических операций и по крайней мере одну условную операцию (если условие истинно, то переход). Три базовые модели , каждая из которых использует три инструкции, взяты из следующей коллекции. (Сокращения произвольны.)
Кроме того, машина обычно имеет инструкцию HALT, которая останавливает машину (обычно после вычисления результата).
Используя приведенные выше инструкции, различные авторы обсуждали определенные счетные машины:
Три базовые модели счетчиковых машин имеют одинаковую вычислительную мощность, поскольку инструкции одной модели могут быть получены из инструкций другой. Все они эквивалентны вычислительной мощности машин Тьюринга . Из-за своего унарного стиля обработки счетчиковые машины обычно экспоненциально медленнее сопоставимых машин Тьюринга.
Модели счетных машин имеют ряд различных названий, которые могут помочь различать их по их особенностям. Ниже инструкция "JZDEC ( r )" является составной инструкцией, которая проверяет, пуст ли регистр r; если да, то перейти к инструкции I z , иначе, если нет, то выполнить декрементацию содержимого r:
Счетная машина состоит из:
В этом примере показано, как создать еще три полезные инструкции: очистку , безусловный переход и копирование .
После этого r s будет содержать свой исходный счетчик (в отличие от MOVE, который очищает исходный регистр, т.е. обнуляет его).
Базовый набор (1) используется так, как определено здесь:
Инструкция | Эффект на регистр "j" | Влияние на регистр счетчика инструкций ICR | Краткое содержание |
---|---|---|---|
ВКЛ (j) | [дж] +1 → дж | [ИК] +1 → ИК | Увеличить содержимое регистра j; следующая инструкция |
ДЕК (j) | [дж] -1 → дж | [ИК] +1 → ИК | Уменьшить содержимое регистра j; следующая инструкция |
JZ (j, z) | ЕСЛИ [j] = 0 ТО I z → IC ИНАЧЕ [IC] +1 → IC | Если содержимое регистра j=0, то инструкция z, иначе следующая инструкция. | |
ОСТАНОВИТЬ |
Изначально регистр № 2 содержит «2». Регистры № 0, № 1 и № 3 пусты (содержат «0»). Регистр № 0 остается неизменным на протяжении всех вычислений, поскольку он используется для безусловного перехода. Регистр № 1 — это временная память. Программа начинается с инструкции 1.
Программа останавливается с содержимым регистра №2, равным его исходному значению, и содержимым регистра №3, равным исходному содержимому регистра №2, т. е.
Программа COPY ( #2, #3) состоит из двух частей. В первой части программа перемещает содержимое исходного регистра #2 как в блокнот #1, так и в целевой регистр #3; таким образом, #1 и #3 будут копиями друг друга и исходного счетчика в #2, но #2 очищается в процессе его уменьшения до нуля. Безусловные переходы J (z) выполняются путем проверки регистра #0, который всегда содержит число 0:
Во второй части программа перемещает (возвращает, восстанавливает) содержимое блокнота №1 обратно в №2, очищая при этом блокнот №1:
Программа, выделенная желтым цветом, отображается слева направо в правом верхнем углу.
Ниже показан "запуск" программы. Время идет по странице. Инструкции выделены желтым цветом, регистры — синим. Программа перевернута на 90 градусов, номера инструкций (адреса) находятся сверху, мнемоники инструкций — под адресами, а параметры инструкций — под мнемониками (по одному на ячейку):
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ← Номер инструкции (адрес) | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Дж.З. | ДЕКАБРЬ | ИНК | ИНК | Дж.З. | Дж.З. | ДЕКАБРЬ | ИНК | Дж.З. | ЧАС | ← Инструкция | |||||||||||||||
2 | 2 | 3 | 1 | 0 | 1 | 1 | 2 | 0 | ← Регистрационный номер | ||||||||||||||||
6 | 1 | 10 | 6 | ← Перейти к номеру инструкции | |||||||||||||||||||||
шаг | IC | Инст # | рег # | J-адрес | рег0 | рег1 | рег2 | рег3 | рег4 | IC | |||||||||||||||
начинать | 0 | 0 | 2 | 0 | 0 | 1 | переместить [#2] в #1 и #3: | ||||||||||||||||||
1 | 1 | Дж.З. | 2 | 6 | 0 | 0 | 2 | 0 | 0 | 1→2 | Дж.З. | Переход не удался: регистр №2 содержит 2 | |||||||||||||
2 | 2 | ДЕКАБРЬ | 2 | 0 | 0 | 0 | 2→1 | 0 | 0 | 2→3 | ДЕКАБРЬ | Уменьшить регистр №2 с 2 до 1 | |||||||||||||
3 | 3 | ИНК | 3 | 0 | 0 | 0 | 1 | 0→1 | 0 | 3→4 | ИНК | Увеличить регистр №3 с 0 до 1 | |||||||||||||
4 | 4 | ИНК | 1 | 0 | 0 | 0→1 | 1 | 1 | 0 | 4→5 | ИНК | Увеличить регистр №1 с 0 до 1 | |||||||||||||
5 | 5 | Дж.З. | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 5→1 | Дж.З. | U-Jump: регистр №0 пуст | |||||||||||||
6 | 1 | Дж.З. | 2 | 6 | 0 | 1 | 1 | 1 | 0 | 1→2 | Дж.З. | Переход не удался: регистр №2 содержит 1 | |||||||||||||
7 | 2 | ДЕКАБРЬ | 2 | 0 | 0 | 1 | 1→0 | 1 | 0 | 2→3 | ДЕКАБРЬ | Уменьшить регистр №2 с 1 до 0 | |||||||||||||
8 | 3 | ИНК | 3 | 0 | 0 | 1 | 0 | 1→2 | 0 | 3→4 | ИНК | Увеличить регистр №3 с 1 до 2 | |||||||||||||
9 | 4 | ИНК | 1 | 0 | 0 | 1→2 | 0 | 2 | 0 | 4→5 | ИНК | Увеличить регистр №1 с 1 до 2 | |||||||||||||
10 | 5 | Дж.З. | 0 | 1 | 0 | 2 | 0 | 2 | 0 | 5→1 | Дж.З. | U-Jump: регистр №0 пуст | |||||||||||||
11 | 1 | Дж.З. | 2 | 6 | 0 | 2 | 0 | 2 | 0 | 1→6 | Дж.З. | Перейти!: регистр №2 пуст | |||||||||||||
переместить [1] в 2: | |||||||||||||||||||||||||
12 | 6 | Дж.З. | 1 | 10 | 0 | 2 | 0 | 2 | 0 | 6→7 | Дж.З. | Переход не удался: регистр № 1 содержит 2 | |||||||||||||
13 | 7 | ДЕКАБРЬ | 1 | 0 | 0 | 2→1 | 0 | 2 | 0 | 7→8 | ДЕКАБРЬ | Уменьшить регистр №1 с 2 до 1 | |||||||||||||
14 | 8 | ИНК | 2 | 0 | 0 | 1 | 0→1 | 2 | 0 | 8→9 | ИНК | Увеличить регистр №2 с 0 до 1 | |||||||||||||
15 | 9 | Дж.З. | 0 | 6 | 0 | 1 | 1 | 2 | 0 | 9→6 | Дж.З. | U-Jump: регистр №0 пуст | |||||||||||||
16 | 6 | Дж.З. | 1 | 10 | 0 | 1 | 1 | 2 | 0 | 6→7 | Дж.З. | Переход не удался: регистр № 1 содержит 1 | |||||||||||||
17 | 7 | ДЕКАБРЬ | 1 | 0 | 0 | 1→0 | 1 | 2 | 0 | 7→8 | ДЕКАБРЬ | Уменьшить регистр №1 с 1 до 0 | |||||||||||||
18 | 8 | ИНК | 2 | 0 | 0 | 0 | 1→2 | 2 | 0 | 8→9 | ИНК | Увеличить регистр №2 с 1 до 2 | |||||||||||||
19 | 9 | Дж.З. | 0 | 6 | 0 | 0 | 2 | 2 | 0 | 9→6 | Дж.З. | U-Jump: регистр №0 пуст | |||||||||||||
20 | 6 | Дж.З. | 1 | 10 | 0 | 0 | 2 | 2 | 0 | 6→10 | Дж.З. | Перейти!: регистр №1 пуст | |||||||||||||
21 | 10 | ЧАС | 0 | 0 | 0 | 0 | 2 | 2 | 0 | 10→10 | ЧАС | ОСТАНОВИТЬ |
Пример выше демонстрирует, как первые базовые инструкции { INC, DEC, JZ } могут создать еще три инструкции — безусловный переход J, CLR, CPY. В некотором смысле CPY использовал как CLR, так и J плюс базовый набор. Если бы регистр № 3 изначально имел содержимое, сумма содержимого № 2 и № 3 оказалась бы в № 3. Поэтому, чтобы быть полностью точной, программа CPY должна была предварять свои ходы CLR (1) и CLR (3).
Однако мы видим, что ADD было бы возможно, легко. И на самом деле, ниже приводится краткое изложение того, как могут возникнуть примитивные рекурсивные функции, такие как ADD, MULtiply и EXPonent. [2]
В общем, мы можем построить любую частично- или полностью примитивную рекурсивную функцию , которую мы хотим, используя те же методы. Действительно, Минский (1967), Шепердсон–Стерджис (1963) и Булос–Берджесс–Джеффри (1974) дают демонстрации того, как сформировать пять примитивных рекурсивных функций «операторов» (1-5 ниже) из базового набора (1).
Но как насчет полной эквивалентности Тьюринга ? Нам нужно добавить шестой оператор — оператор μ — чтобы получить полную эквивалентность, способную создавать полностью и частично рекурсивные функции :
Авторы показывают, что это легко сделать в любом из доступных базовых наборов (1, 2 или 3) (пример можно найти в операторе μ ). Это означает, что любая рекурсивная функция mu может быть реализована как счетчиковая машина [3], несмотря на конечный набор инструкций и размер программы конструкции счетчиковой машины. Однако требуемая конструкция может быть контринтуитивной, даже для функций, которые относительно легко определить в более сложных регистровых машинах, таких как машина с произвольным доступом . Это связано с тем, что оператор μ может выполнять итерации неограниченное количество раз, но любая заданная счетчиковая машина не может адресовать неограниченное количество различных регистров из-за конечного размера ее списка инструкций.
Например, вышеприведенная иерархия примитивных рекурсивных операторов может быть расширена за пределы возведения в степень в операции со стрелками более высокого порядка в обозначении стрелки вверх Кнута . Для любого фиксированного функция является примитивно рекурсивной и может быть реализована как счетчик-машина простым способом. Но функция не является примитивно рекурсивной. Может возникнуть соблазн реализовать оператор стрелки вверх с помощью конструкции, аналогичной инструкциям преемника, сложения, умножения и возведения в степень выше, путем реализации стека вызовов , чтобы функцию можно было применять рекурсивно к меньшим значениям . Эта идея похожа на то, как можно реализовать функцию на практике во многих языках программирования. Однако счетчик-машина не может использовать неограниченное количество регистров в своих вычислениях, что было бы необходимо для реализации стека вызовов, который может расти произвольно большим. Операция «стрелка вверх» по-прежнему может быть реализована как счетная машина, поскольку она является мю-рекурсивной, однако функция будет реализована путем кодирования неограниченного объема информации внутри конечного числа регистров, например, с использованием нумерации Гёделя .
(1) Неограниченные емкости регистров против ограниченных емкостей инструкций конечного автомата: как машина будет создавать константы, превышающие емкость ее конечного автомата?
(2) Неограниченное количество регистров против ограниченного количества инструкций конечного автомата: как машина будет получать доступ к регистрам с адресами, номерами, выходящими за пределы досягаемости/возможностей ее конечного автомата?
(3) Полностью редуцированные модели громоздки:
Шепердсон и Стерджис (1963) не извиняются за свой набор из 6 инструкций. Они сделали свой выбор на основе «простоты программирования... а не экономии» (стр. 219, сноска 1).
Инструкции Шепердсона и Стерджиса ([r] указывает на «содержимое регистра r»):
Минский (1967) расширил свой набор из 2 инструкций {INC (z), JZDEC (r, I z )} до {CLR (r), INC (r), JZDEC (r, I z ), J (I z )}, прежде чем доказать, что «универсальная программная машина» может быть построена всего с двумя регистрами (стр. 255 и далее).
Для каждой машины Тьюринга существует 2CM, которая ее имитирует, при условии, что вход и выход 2CM правильно закодированы. Это доказано в книге Мински ( Computation , 1967, стр. 255-258), а альтернативное доказательство изложено ниже в три шага. Во-первых, машину Тьюринга можно имитировать с помощью конечного автомата (FSM), оснащенного двумя стеками. Затем два стека можно имитировать четырьмя счетчиками. Наконец, четыре счетчика можно имитировать двумя счетчиками. Машина с двумя счетчиками использует набор инструкций { INC ( r, z ), JZDEC ( r, z true , z false ) }.
Машина Тьюринга состоит из конечного автомата и бесконечной ленты, изначально заполненной нулями, на которую машина может записывать единицы и нули. В любой момент времени головка чтения/записи машины указывает на одну ячейку на ленте. Эту ленту можно концептуально разрезать пополам в этой точке. Каждую половину ленты можно рассматривать как стек , где верх — это ячейка, ближайшая к головке чтения/записи, а низ находится на некотором расстоянии от головки, со всеми нулями на ленте за пределами дна. Соответственно, машину Тьюринга можно смоделировать с помощью конечного автомата плюс два стека. Перемещение головки влево или вправо эквивалентно извлечению бита из одного стека и проталкиванию его в другой. Запись эквивалентна изменению бита перед его проталкиванием.
Стек, содержащий нули и единицы, можно смоделировать двумя счетчиками, когда биты в стеке рассматриваются как представляющие двоичное число (самый верхний бит в стеке является наименее значимым битом). Помещение нуля в стек эквивалентно удвоению числа. Помещение единицы эквивалентно удвоению и добавлению 1. Извлечение эквивалентно делению на 2, где остаток — это бит, который был извлечен. Два счетчика могут имитировать этот стек, в котором один из счетчиков хранит число, двоичное представление которого представляет биты в стеке, а другой счетчик используется в качестве блокнота. Чтобы удвоить число в первом счетчике, FSM может инициализировать второй счетчик нулем, затем многократно уменьшать первый счетчик один раз и увеличивать второй счетчик дважды. Это продолжается до тех пор, пока первый счетчик не достигнет нуля. В этот момент второй счетчик будет содержать удвоенное число. Деление пополам выполняется путем уменьшения одного счетчика дважды и увеличения другого один раз, и повторения, пока первый счетчик не достигнет нуля. Остаток можно определить по тому, достиг ли он нуля после четного или нечетного числа шагов, причем четность числа шагов закодирована в состоянии конечного автомата.
Как и прежде, один из счетчиков используется в качестве блокнота. Другой содержит целое число , разложение которого на простые множители равно 2 a 3 b 5 c 7 d . Показатели a , b , c и d можно рассматривать как четыре виртуальных счетчика, которые упаковываются (с помощью нумерации Гёделя ) в один действительный счетчик. Если действительный счетчик установлен в ноль, а затем увеличен один раз, это эквивалентно установке всех виртуальных счетчиков в ноль. Если действительный счетчик удваивается, это эквивалентно увеличению a , а если он уменьшается вдвое, это эквивалентно уменьшению a . С помощью аналогичной процедуры его можно умножить или разделить на 3, что эквивалентно увеличению или уменьшению b . Аналогично можно увеличить или уменьшить c и d . Чтобы проверить, равен ли виртуальный счетчик, такой как c , нулю, просто разделите действительный счетчик на 5, посмотрите, чему равен остаток, затем умножьте на 5 и прибавьте остаток. Это оставляет реальный счетчик неизменным. Остаток будет ненулевым тогда и только тогда, когда c будет нулевым.
В результате FSM с двумя счетчиками может имитировать четыре счетчика, которые в свою очередь имитируют два стека, которые имитируют машину Тьюринга. Следовательно, FSM плюс два счетчика по крайней мере так же мощны, как машина Тьюринга. Машина Тьюринга может легко имитировать FSM с двумя счетчиками, поэтому обе машины имеют эквивалентную мощность.
Этот результат, вместе со списком других функций от N , которые не вычисляются двухсчетчиковой машиной — при инициализации с N в одном счетчике и 0 в другом — таких как N 2 , sqrt( N ), log 2 ( N ) и т. д., появляется в статье Шреппеля (1972). Результат неудивителен, поскольку модель двухсчетчиковой машины была доказана (Мински) как универсальная только тогда, когда аргумент N соответствующим образом закодирован (с помощью Гёделизации) для имитации машины Тьюринга, начальная лента которой содержит N, закодированное в унарной системе; более того, вывод двухсчетчиковой машины будет закодирован аналогичным образом. Это явление типично для очень малых баз вычислений, универсальность которых доказана только с помощью моделирования (например, многие тарпиты Тьюринга , наименьшие известные универсальные машины Тьюринга и т. д.).
Доказательству предшествуют некоторые интересные теоремы:
Что касается второй теоремы о том, что «3CM может вычислить любую частично рекурсивную функцию», автор бросает вызов читателю, предлагая «Сложную задачу: умножить два числа, используя только три счетчика» (стр. 2). Основное доказательство включает в себя представление о том, что машины с двумя счетчиками не могут вычислять арифметические последовательности с нелинейными темпами роста (стр. 15), то есть «функция 2 X растет быстрее, чем любая арифметическая прогрессия» (стр. 11).
Этот раздел, возможно, содержит оригинальные исследования . ( Апрель 2024 г. ) |
Калькулятор Friden EC-130 не имел логики сумматора как таковой. Его логика была в высшей степени последовательной, выполняя арифметику путем подсчета. Внутренне десятичные цифры были с основанием 1 — например, шестерка была представлена шестью последовательными импульсами в пределах временного интервала, выделенного для этой цифры. Каждый временной интервал переносил одну цифру, наименее значимую первой. Переносы устанавливали триггер, который заставлял один счет добавляться к цифре в следующем временном интервале.
Сложение производилось с помощью счетчика с прибавлением, а вычитание — с помощью счетчика с вычитанием, при этом использовалась аналогичная схема для обработки заемных средств.
Схема временного интервала определяла шесть регистров из 13 десятичных цифр, каждый со знаковым битом. Умножение и деление выполнялись в основном путем повторного сложения и вычитания. Версия квадратного корня, EC-132, эффективно вычитала последовательные нечетные целые числа, каждое уменьшение требовало двух последовательных вычитаний. После первого уменьшаемое увеличивалось на единицу перед вторым вычитанием.