Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1 Примитивно рекурсивные функции.doc
Скачиваний:
3
Добавлен:
01.03.2025
Размер:
192 Кб
Скачать

Другие виды рекурсии

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

Мы приведем два примера последнего типа: совместное определение нескольких функций и использование произвольных меньших значений аргумента.

Совместная рекурсия. Пусть две одноместные функции f и g заданы соотношениями:

f(0) = a,

g(0) = b,

f(n+1) = F(n,f(n),g(n)),

g(n+1) = G(n,f(n),g(n)),

где a и b некоторые числа, а функции F и G примитивно рекурсивные функции трех аргументов. Покажем, что тогда функции f и g примитивно рекурсивны.

Чтобы доказать это, нам потребуется примитивно рекурсивная нумерация пар такая функция (номер пары мы обозначаем квадратными скобками), которая была бы примитивно рекурсивна вместе с двумя обратными функциями (дающими по номеру пары ее первый и второй члены). Тогда мы сможем написать рекурсивное определение для функции h(n)=[f(n),g(n)]:

h(0) = [a,b],

h(n+1) = [F(n,p1(h(n)),p2(h(n))),G(n,p1(h(n)),p2(h(n)))],

где функции p1 и p2 дают по номеру пары первый и второй ее члены. Если функция h примитивно рекурсивна, то и функции f и g (композиции h с функциями p1 и p2 ) также примитивно рекурсивны.

Осталось объяснить, как найти примитивно рекурсивную нумерацию пар. Можно заметить, что есть многочлен второго порядка с двумя переменными, задающий взаимно однозначное соответствие N x N -> N. Это соответствие видно из таблицы:

6

3  7 

1  4  8 

0  2  5  9

Примитивную рекурсивность обратных отображений p1 и p2 можно установить, воспользовавшись ограниченной минимизацией, так как p1(n) есть минимальное x <= n, для которого найдется y <= n, при котором [x,y]=n.

Менее симметричная нумерация пар может быть задана формулой [a,b]=(2a+1)2b-1. Можно также заметить, что нам не нужно, чтобы все числа были номерами каких-то пар, и воспользоваться нумерацией [a,b]=2a3b.

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

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

Теорема 74. Пусть функция g одного аргумента примитивно рекурсивна, причем g(x)<x при x>0 ; пусть F примитивно рекурсивная функция двух аргументов; пусть c произвольная константа. Тогда функция h, определенная соотношениями

h(0) = c,

h(x) = F(x,h(g(x))) при x>0

примитивно рекурсивна.

Чтобы доказать эту теорему, используем следующую нумерацию конечных последовательностей натуральных чисел: номером пустой последовательности считаем число 1, номером одноэлементной последовательности считаем число 2a+1, последовательность имеет номер 2a+13b+1, последовательность имеет номер 2a+13b+15c+1 и так далее (основания степеней простые числа). Будем обозначать номер последовательности через [a,b,...,z]. Эта нумерация в некотором смысле примитивно рекурсивна. Конечно, буквально это понимать нельзя, так как нумерация представляет собой " функцию с переменным числом аргументов". Но разные связанные с ней функции примитивно рекурсивны. В частности, таковы функции

  • Length(x) = длина последовательности с номером x ;

  • Select(i,x)=i -ый член последовательности с номером x ;

  • Append(x,y)= номер последовательности, которая получается приписыванием числа y к последовательности с номером x.

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

Теперь мы докажем, что функция

примитивно рекурсивна. В самом деле, H(0)=[c], а

H(k+1)= Append(H(k),F(k+1,Select(g(k+1),H(k)))).

Задание.

  1. “Задача о коровах”

Есть два утверждения:

1) три коровы — это стадо коров;

2) стадо из n > 3 коров — это стадо из n – 1 коровы и еще одна корова,

— о которых можно сказать, что это — рекурсивное определение понятия “стадо коров”.

Необходимо, используя это определение, проверить, является ли стадом группа из пяти коров (обозначим ее К5).

  1. Рекурсивная функция для расчета факториала заданного числа n:

  2. Доказать, что функция примитивно рекурсивна

.

Постройте данную функцию.

  1. С помощью рекуррентных формул опишите числа Фибоначчи

О, 1, 1, 2, 3, 5, ...

  1. Функция Аккермана определяется рекурсивно для неотрицательных целых чисел и следующим образом:

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

Машины Тьюринга и рекурсивные функции

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

Теорема 75. Любая функция, вычислимая на машине Тьюринга не более чем за примитивно рекурсивное (от длины входа) время, примитивно рекурсивна.

Напомним, что мы считаем входом и выходом машины Тьюринга слова из нулей и единиц. Поскольку аргументами и значениями примитивно рекурсивных функций являются числа, теорема будет иметь смысл, только если мы договоримся отождествлять числа и слова. Как уже говорилось, мы отождествляем число n со словом, которое получается после удаления старшего бита 1 в двоичном разложении числа n+1.

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

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

Это рассуждение неявно использует примитивную рекурсивность различных функций, связанных с переходом от одного представления данных к другому. Например, вход машины Тьюринга является двоичным словом, которое мы договорились отождествлять с некоторым числом x. Этому входу соответствует начальная конфигурация машины Тьюринга, которую мы кодируем четверкой чисел. Нам важно, что эта четверка примитивно рекурсивно зависит от x. Это легко понять, так как преобразование связано с переходом от одной системы счисления к другой (одно и то же слово кодирует разные числа в разных системах счисления); примитивную рекурсивность таких функций легко установить с помощью описанных выше методов. Кроме того, нам надо из выходной конфигурации примитивно рекурсивно извлечь результат и также перекодировать его, а также по входу получить его длину (чтобы подставить в примитивно рекурсивную функцию, ограничивающую число шагов). Но все это также не выходит из круга разобранных выше приемов, и подробно останавливаться на этом мы не будем.

Эта теорема убеждает нас в примитивной рекурсивности многих довольно сложно определяемых функций. Например, рассмотрим функцию n ( n -ый десятичный знак числа ). Известно, что вычислены миллионы таких знаков, поэтому есть все основания полагать, что известные алгоритмы работают не слишком долго было бы очень странно, если бы время их работы (даже учитывая неудобство машины Тьюринга для программирования) не оценивалось бы, скажем, функцией cx 2n при достаточно большом c. А такая оценка примитивно рекурсивна, что позволяет сослаться на только что доказанную теорему. (На самом деле тут большой запас существуют примитивно рекурсивные функции, которые растут гораздо быстрее 2n.)

Другое описание класса примитивно рекурсивных функций, более понятное программистам: это функции, которые можно вычислять программой, содержащей if-then-else -ветвления и for -циклы, но не содержащие while -циклов (и тем более go to и разных других пакостей типа изменения параметра for-цикла внутри цикла).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]