Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
29
Добавлен:
14.04.2015
Размер:
246.78 Кб
Скачать

2.2. Вычислимые и рекурсивные функции.

Арифметическая функция y=j(x1, x2, ...,xn) - это целочисленные функции, зависящие от целочисленных значений аргументов, т.е. это функция, построенная на множестве {0, 1, 2, ...}. Под f понимается суперпозиция операций сложения, вычитания, умножения и деления, операций определения абсолютного значения результата при вычитании и целой части - при делении, а также некоторых специальных операций, например,

min(x, y) = .

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

Арифметические функции, значения которых можно вычислять посредством некоторого алгоритма, называются вычислимыми функциями. Понятие “вычислимые функции”, основанное на интуитивном смысле алгоритма, также является интуитивным. Однако между ними имеется существенная разница: совокупность вычислителных процессов, удовлетворяющих признакам 1-5 алгоритма (п. В.1), очень обширна; напротив, совокупность вычислимых функций для самых разных процессов, удовлетворяющих признакам 1-5, оказалась одной и той же, и при том легко описываемой в обычных математических терминах. Точно описанная совокупность арифметических функций, совпадающая с совокупностью всех вычислимых функций при самом широком до сих пор известном понятии алгоритма (см. признаки 1-5), носит название совокупности рекурсивных функций.

2.2.1. Построение класса примитивно-рекурсивных функций

Рассмотрим, каким образом может быть построен класс рекурсивных функций.

Определение. Функция y=j(x1, x2, ..., xn) называется алгоритмически вычислимой (просто вычислимой), если существует алгоритм, позволяющий определить значение функции при любых значениях переменных х1, х2, ..., хn.

Определение. Предикат Р(х1, х2, ..., хn), определённый на множестве целых чисел, называется алгоритмически разрешимым (просто разрешимым), если существует алгоритм для определения значений предиката Р при любых значениях переменных х1, х2, ..., хn.

Эти определения являются неточными, поскольку ещё не сформулировано точно понятие алгоритма. Для их уточнения построим класс вычислимых функций, начав с элементарных. Элементарными являются все функции вида:

j(x)=x+1, j(y)=12y, y(a, b, c)=ab+c, l(b)=b2 (=bb) и т.п.

Рассмотрим эти функции подробнее. Если в функции j(x)=x+1 положить x=0 (начальное значение) и затем многократно использовать эту формулу с предыдущим значением, то таким путём мы можем получить все числа натурального ряда. Многократное применение одной и той же формулы (вычислительного процесса) называют итерацией. Операцию сложения двух чисел a+b можно представить как применение формулы x+1 b раз, если в качестве начального значения x положить a; таким образом, сложение двух целых чисел - это итерация добавления единицы. Нетрудно видеть, что произведение an=a+a+...+a - n раз повторенное сложение (умножение - итерация сложения).

Функция y может быть представлена в видеy=d+c, где d=ab, так что y включает в себя две операции: умножение, как итерацию сложения, и операцию сложения, как итерацию добавления единицы (в последнем случае полагаем d начальным значением для x). Все эти функции растут довольно медленно и по этому признаку их относят к элементарным.

Рассмотрим операцию возведения в степень. Для функции l(b) имеем bn= bb...b - n раз повторенное умножение на число b, то есть это итерация умножения: bn =. Эта функция, хотя и растёт довольно быстро, является ещё элементарной, так как она выражается через произведение.

Построим еще более быстро растущую функцию, которая является итерацией возведения в степень: y(0, a)=a, y(1, a)=aa, y(2, a)= ... !!!, и вообще,

y(n+1, a)=a y(n, a) . (2.1)

Функция (2.1) растёт чрезвычайно быстро; эта функция, начиная с некоторого а=а*, мажорирует все элементарные функции, то есть для любой элементарной функции j(a) найдётся такое число m*, что будет выполняться неравенство j(а)<y(m*, a) для всех аа*.

Таким образом, итерация возведения в степень позволяет получить неэлементарную функцию. В то же время y(n, a) заведомо вычислима. Действительно, пусть мы хотим вычислить значение y(n, a) при любых n=n*, a=a*. При a=a* формула (2.1) даёт

y (n+1, a*)=(a*) y (n, a*) . ( 2.1’)

Обозначим (a*)m = l(m); l(m)- элементарная, всюду однозначно вычислимая функция. Алгоритм её вычисления сводится к повторенному m раз умножению на a*. Запись (см. (2.1’))

y(n+1, a*)=l(y (n, a*)) (2.2)

связывает значение функции y в данной точке с её значением в предыдущей точке.

Достаточно теперь задать начальное значение y(0, a*) = a*, чтобы получить вычислительную процедуру, которая последовательно даёт следующие значения:

y(1, a*)= l(y(0, a*))= l(a*),

y (2, a*)= l(y (1, a*))= l(l(a*)),

y(3, a*)= l(y(2, a*))= l(l(l(a*))),

. . .

Этот процесс следует продолжать, пока не будет достигнуто значение y(n*, a*).

Очевидно, этим способом функция y определена всюду и однозначно, так как вычисление её значений сводится к вычислению значений функции l(m), которая является всюду определённой и однозначной.

Рассмотрим подробнее способ определения функции y(n, a). Эта функция была задана по индукции: было задано начальное значение функции y(0, a), и был указан способ вычисления её значения по предыдущим значениям с помощью допустимых операций. Как видим, был применён метод математической индукции. Используем этот метод в качестве основы для определения вычислимой функции, Но сперва несколько уточним и расширим схему определения по индукции.

Обозначим через x¢ функцию “следовать за”, которая означает переход к следующему элементу заданного множества; для множества натуральных чисел функция x¢ совпадает с x+1. Общую схему определения вычислимой функции j(x) теперь можно уточнить следующим образом:

1) задано j(0);

2) для любого x указывается, каким образом значение j(x¢) выражается в терминах x и j (x):

j(0)=q, j(x¢)=l(x, j(x)). (2.3)

В более общем случае в функции j могут присутствовать ещё и неизменяемые в процессе индукции параметры x2, x3, ..., xn (обозначим ). Схема (2.3) тогда будет иметь вид:

j(0, )=y()

j(y¢ ,)=l(y, j(y, ),(2.4)

Если фунции y и l известны и вычислимы, то с помощью схемы (2.4) для заданных x2=x2*, x3=x3*, ..., может быть организована процедура вычисления последовательно

j(1, ), j(2, )и т. д. Следовательно, схема, заданная выражениями (2.4), действительно определяет вычислимую функцию.

Добавим к описанной функции x¢ также функцию-константу и функцию-тождество. Эти три функции будем считать первоначально известными или просто первоначальными.

Итак, мы имеем следующие первоначальные функции:

I. j(x)=x¢ - описанная выше функция следования, применённая для множества натуральных чисел.

II. j()=q, где q - функция-константа.

III. j()=xi - функция-тождество.

Включим в число допустимых операций схему подстановки:

IV. j()=y(l1(),l 2(), ..., l m()).

И наконец, введём в систему допустимых операций схемы (2.3) и (2.4) определения вычислимой функции:

Va - соответствует схеме (2.3),

Vb - соответствует схеме (2.4).

Итак, схемы I-III задают первоначальные функции (как бы играют роль аксиом), а IV и V - правила вывода. Применяя многократно эти схемы, можно построить обширный класс вычислимых функций.

Определение. Функция j() называется примитивно-рекурсивной, если она может быть определена с помощью конечного числа применений схем I-V.

Это определение раскрывает механизм построения класса примитивно-рекурсивных функций; этот класс включает в себя подкласс всех элементарных функций.

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

и .

Рассмотрим пример построения примитивно-рекурсивной функции.

Пример 2.2.. Определим функцию j(n, x) так:

j(0, x)=x, (A) j(y¢, x)=(j(y, x))¢. (B)

Согласно этой схеме имеем:

j(1, x) = (j(0, x))¢ = x¢ = x+1,

j(2, x) = (j(1, x))¢ = ( x+1)¢ = x+1+1 = x+2,

j(3, x) = (j(2, x))¢ = (x+2)¢ = x+3, и вообще j(n, x)=x+n .

Назовём представляющей функцией предиката P()такую функцию j(), которая обращается в нуль лишь для тех и только тех x1, x2, ..., xn, для которых P()истинно. Тогда истинность P() соответствует равенству j() = 0.

Определение. Предикат называется примитивно-рекурсивным, если существует примитивно-рекурсивная функция, представляющая этот предикат.

Из сущности механизма построения класса примитивно-рекурсивных функций видно, что каждая примитивно-рекурсивная функция является вычислимой. Верно ли обратное утверждение: всякая вычислимая функция - примитивно-рекурсивная? Иначе: все ли вычислимые функции охватывает этот механизм? Ответ на этот вопрос даётся в следующем параграфе.

2.2.2. Построение класса общерекурсивных функций

Математиками были предприняты попытки построения вычислимых функций, не являющихся примитивно-рекурсивными, и такие функции были получены Это позволило сделать вывод, что класс примитивно-рекурсивных функций не охватывает всех вычислимых функций и нуждается в расширении. Однако нас ограничивает, прежде всего, принятая форма индукции (схема V), которая определяет функцию j через уже известные функции l и j.

Пример 2.3. Пусть для примера 2.2 нас интересует значение j(3, 5). Формально проанализируем, какие операции нам нужно совершить, чтобы пользуясь схемой (A) и (B), вычислить j (3, 5).

1. Подставим в (B) вместо переменных числа n=2, x=5. Получим j(3, 5)=j(2, 5)+1.

2. Подставим в (B) n=1, x=5 и определим j(2, 5): j(2, 5)=j(1, 5)+1.

3. Аналогично получим j(1, 5)=j(0, 5)+1.

4. Подставим в (A) x=5. Получимj(0, 5)=5.

5. Заменим в выражении пункта 3 j(0, 5) на 5, согласно пукту 4:

j(1, 5)=5+1=6.

6. Заменив j(1, 5) в выражении пункта 2 её значением из пункта 5, получим

j(2, 5)=6+1=7.

7. Наконец, заменив j(2, 5) в выражении пункта 1 её значением из пункта 6, получим

j(3, 5)=7+1=8.

В рассмотренном примере нам для организации вычислений понадобилось лишь две операции:

1) подстановка чисел на место переменных;

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

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

Определение. Функция j() называется общерекурсивной, если существует такая конечная система равенств Е, что для любого набора чисел найдётся такое одно и только одно числоy*, что равенство j()=y* может быть выведено из Е с помощью конечного числа применений операций подстановок числа на место переменных и замены вхождений.

Говорят, что Е рекурсивно определяет функцию j. Здесь не требуется, чтобы значения функции вычислялись с помощью её значений в предыдущих точках; не требуется, чтобы входящие в систему Е вспомогательные функции были всюду вычислимы; не фиксируется никакая схема индукции. Требуется только, чтобы система равенств Е так определяла данное значение j с помощью других значений j и некоторых значений вспомогательных функций, чтобы j во всех точках можно было однозначно вычислять на основании системы Е.

Приведенное определение общерекурсивной функции не конструктивно, так как не раскрывает механизма вычислительной процедуры нахождения числа y*. Можно, конечно, попробовать выводить из Е все возможные равенства до тех пор, пока не встретится равенство, которое нас интересует. Однако при таком подходе нет никакой гарантии, что этот процесс перебора не продлится неопределённо долго (ср. с лабиринтом).

Процессу перебора можно придать определённую регулярность, так чтобы этот процесс годился для вывода равенства j()=y* за конечное, но не ограниченное заранее число шагов.

Отметим, что равенство j()=y* может быть представлено в эквивалентной форме y(, y)=0. Последнее равенство в общем случае имеет вид y(, y)=0; этому выражению может быть поставлен в соответствие предикат P(, y), истинный в случае y=0..

Гёдель предложил метод сведения любого алгоритма к численному алгоритму путём специальным образом организованной нумерации любых выражений. Этот метод носит название гёделизация. Рассмотрим этот метод.

Включим все условия задачи, доступные для переработки данным алгоритмом A, в занумерованную неотрицательными целыми числами последовательность A0, A1, A2, ..., An, ... Совершенно аналогично записи возможных решений также включим в занумерованную последовательность B0, B1, B2, ..., Bm, ...

Теперь можно любой алгоритм, перерабатывающий запись условий An в запись решения Bm, свести к вычислению значений некоторой числовой функции m= j(n), т.е. можно говорить об алгоритме, который перерабатывает номер записи условия в номер записи решения. Этот алгоритм будет численным алгоритмом.

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

Гёдель предложил рассматривать запись некоторого числа n в форме

n=... где p0=2, p1=3, p2=5 и вообще pm - m-е простое число.

Из этой записи видно (в силу теоремы о единственности разложения любого числа на простые множители), что каждому числу n однозначно соответствует набор a1, a2, .., am и, наоборот, каждому набору a1, a2, ..., am однозначно соответствует число n. Например, при n=60 имеем: 60 = 22 31 51 , т.е. a1 = 2, a2 = 1, a3 = 1.

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

1. Каждой паре чисел a1 и a2, для которой мы ищем её наибольший общий делитель q, может быть поставлен в соответствие гёделевский номер этой пары

n=.. некоторый

Алгоритм Евклида сведётся тогда к вычислению функции q = j(n).

2. Пусть требуется занумеровать все слова в некотором алфавите A. Это легко сделать, поставив в соответствие каждой букве алфавита какое-либо число. Тогда каждому слову в алфавите A будет соответствовать последовательность чисел. Проводя затем обычным способом гёделизацию, получим гёделевский номер этой последовательности. Ясно, что номер слова определяется выбранной системой соответствий между буквами и числами. Теперь легко пронумеровать все последовательности слов (например, все дедуктивные цепочки). Здесь также имеется однозначное соответствие последовательности слов и последовательности гёделевских номеров этих слов. Проведя гёделизацию вторично, мы можем определить гёделевский номер самой последовательности гёделевских номеров отдельных слов.

Итак, с помощью гёделизации арифметические алгоритмы сводятся к вычислению значений целочисленных функций. Аналогично любой нормальный алгоритм Маркова может быть также сведен к вычислению значений целочисленных функций. Поэтому алгоритм вычисления значений целочисленных функций можно считать универсальной формой алгоритма.

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

Оператор наименьшего числа ставит в соответствие примитивно-рекурсивному предикатуP(, y)(или примитивно-рекурсивной функции y(, y), представляющей предикат P ) примитивно-рекурсивную функцию j() следующим образом:

j()=myyz| P(, y)=y yz | y(, y)=0 (2.5)

при условии

(x1)(x2)...(xn) (y)yz | P(, y)(2.6)

или

(x1) (x2) ... (xn) (y)yz |y(, y)=0,(2.7)

где z в общем случае может быть примитивно-рекурсивной функцией переменных

, то есть

z=z(). (2.8)

Утверждение. Любая общерекурсивная функция j() может быть представлена в виде

j()=t{my|y(, y)=0}, (2.9)

где y и - это примитивно-рекурсивные функции, причём для функции y справедливо выражение

(x1) (x2) ... (xn) (y) |y(, y)=0. (2.10)

Типичной ситуацией применения -оператора является построение обратных функций. Допустим, что для некоторой функцииy=f(x) существует обратная функция, то есть для каждого натурального y существует единственное значение x, для которого f(x)=y; в таком случае обратная функция x=j(y) может быть определена посредством -оператора: j(y)=x |f(x)=y.

Многие функции анализа, такие как показательная cx и степенная xc , определены на всём натуральном ряде, если параметр c выбран подходящим образом. Однако этого нельзя утверждать об обратных функциях; например, logcx или , вообще говоря, не будет натуральным числом даже при натуральном c. В таких случаях удобно рассматривать арифметические варианты обратных функций, которые заключаются в следующем: в качестве значений функции объявляется целая часть истинных значений функции, то есть ]j(y)[, где ]x[ - целая часть числа x. Теперь ясно, что исходя из функции у=cx или y=xc, можно определить арифметические обратные функции посредством - оператора:

]logr(y)[ =x | rx+1>y;

][ =x |(x+1) r>y.

Рекурсивное описание называется примитивно-рекурсивным, если в нём не участвует -оператор, то есть допускаются только операторы суперпозиции, введения фиктивных переменных и примитивной рекурсии.

Если к уже известным нам схемам определения примитивно-рекурсивных функций добавить схему VI, составленную из выражений (2.9) и (2.10), то мы получим в результате конечного числа применений схем I-VI общерекурсивную функцию j().

Таким образом, примитивно-рекурсивные функции являются частным случаем общерекурсивных функций; всякая примитивно-рекурсивная функция есть общерекурсивная функция, но не наоборот.