- •Дополнение
- •Наивная теория алгоритмов
- •4.4. Наивная теория алгоритмов
- •4.4.1. Вычислимые функции
- •4.4.2. Перечислимые множества
- •4.4.3. Разрешимые множества
- •4.4.4. Протокол выполнения алгоритма
- •4.4.5. Алгоритмы и программы
- •4.4.6. Невычислимые функции и неразрешимые множества
- •4.4.7. Истинность и доказуемость
- •4.4.8. Множество истин арифметики
4.4.1. Вычислимые функции
Алгоритмы бывают разные. В частности, алгоритмы могут обладать разными возможностями в части вырабатывания результата.
Рассмотрим случай, когда алгоритм A принимает на вход некоторые данные (аргумент) и перерабатывает их в некоторые другие или те же самые данные (результат). Тем самым алгоритм A определяет отношение A между множеством возможных входных данных (обозначение Dom A) и множеством возможных результатов (обозначение Im A),
A Dom A Im A.
Если отношение А обладает свойством функциональности (см. п. 1.6.1), то говорят что алгоритм A реализует вычислимую функцию.
Если функция является вычислимой, то есть если предъявлен реализующий её алгоритм, то может быть построено бесконечно много других алгоритмов, также реализующих эту же функцию. Действительно, для этого достаточно вставлять в тело любого из уже построенных алгоритмов произвольные ненужные операторы, выполнение которых не влияет на результат. Все алгоритмы, реализующие одну и ту же функцию, называются функционально эквивалентными. Функциональная эквивалентность, очевидно, действительно является отношением эквивалентности на классе алгоритмов и определяет фактор-множество (п. 1.7.2) классов функционально эквивалентных алгоритмов. Это фактор-множество взаимно однозначно соответствует классу вычислимых функций, поэтому можно выбрать какой-либо из функционально эквивалентных алгоритмов, объявить его представлением вычислимой функции и использовать в качестве функции везде, где это необходимо, в частности в других алгоритмах для вычисления значения этой функции. Это оправдывает используемые далее вольности в обозначениях и в словесных оборотах, когда вычислимые функции и их представления не различаются, подобно тому, как мы говорим о функции, предъявляя запись реализующей её формулы (п. 3.2.4).
Замечание 1. Для целей наивной теории алгоритмов совершенно не важно, какой именно из функционально эквивалентных алгоритмов представляет вычислимую функцию. Для практического программирования это, напротив, один из главных вопросов, потому что функционально эквивалентные алгоритмы могут драматически отличаться друг от друга по длине записи, по эффективности работы, по степени понятности и т. д.
Замечание 2. Для алгоритмов неизвестно нормальных форм (п. 3.4.2), к сожалению.
В используемом псевдокоде в теле вычислимой функции, как правило, присутствует оператор return.
Для записи вычислимых функций применяются те же обозначения, что и для записи функций:
A : Dom A Im A,
Im A = A(Dom A),
r = A(a), где aDom A, rIm A.
Замечание. Вычислимая функция может быть частичной, т. е. в записи алгоритма A может быть указано, что алгоритм принимает на вход значения типа T1 и выдает на выход значения типа T2 (A: T1 T2), но при этом, на самом деле, Dom A T1 и Im A T2, т. е. область отправления и область прибытия шире области определения и области значений, соответственно. В этом случае считается, что при применении к неподходящему аргументу вычислимая функция не вырабатывает никакого результата. Тем самым наивная теория алгоритмов приближается к суровой программистской практике.
Примеры.
1. Суперпозиция вычислимых функций, очевидно, вычислима. Тем самым любая формула над базисом вычислимых функций задает вычислимую функцию.
2. Алгоритмы 1.3, 1.4–1.7, 3.1–3.5, 4.1 задают вычислимые функции.
Отступление. Понятие тип, или тип данных, использованное в предыдущем замечании, имеет важное значение в программировании. С точки зрения наивной теории алгоритмов тип — это некоторое перечислимое (и разрешимое, см. п. 4.4.3) множество слов в алфавите U. В программировании понятие типа (и родственное понятие класса) применяется, в частности, для проверки правильности применения (частичных) вычислимых функций и алгоритмов. А именно, указывая типы параметров функции, программист задает (до некоторой степени) область определения функции, и система программирования может проверить, принадлежит переданный аргумент указанному типу, или нет (это возможно, поскольку тип — разрешимое множество). Результаты этой проверки могут быть использованы для диагностирования или предотвращения ошибки и других полезных действий. В этом разделе нам не понадобилась теория типов, но это важное и практически полезное ответвление наивной теории алгоритмов.
