Лекция 2. Математическая логика и теория алгоритмов

### II. Элементы теории алгоритмов и рекурсивных функций

1. Понятие алгоритма
2. Машина Тьюринга (МТ)
3. Вычисление функций на МТ
4. Алгоритмически неразрешимые задачи
5. Примитивно рекурсивные функции
6. Частично рекурсивные функции
7. Характеристики сложности алгоритмов
8. Классы сложности P и NP
9. Контрольные вопросы

### 1. Понятие алгоритма

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

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

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

Алгоритм – это совокупность правил, соблюдение которых при вычислениях приводит к решению поставленной задачи. Это неформальное определение алгоритма, известное еще со времен Аль Хорезми (IX век). Можно выделить некоторые черты, присущие каждому алгоритму:

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

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

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

### 2. Машина Тьюринга (МТ)

Первый важный и достаточно широкий класс алгоритмов был описан Аланом Матисоном Тьюрингом и Эмилем Леоном Постом в 1936-1937гг. Алгоритмы этого класса осуществляются особыми машинами, называемыми в настоящее время машинами Тьюринга-Поста или просто машинами Тьюринга. Машины Тьюринга копируют в существенных чертах работу человека, вычисляющего по заданной программе, и часто рассматриваются в качестве математической модели для изучения функционирования человеческого мозга.

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

Английский математик А.М.Тьюринг в 1937 году впервые предложил модель вычислительной машины, известной теперь под названием машина Тьюринга, которая представляет собой воображаемую машину или математическую модель машины.

Машина Тьюринга (MT) – чистая абстракция и никогда не была реализована. Польза от нее в том, что с ее помощью можно доказать существование или несуществование алгоритмов решения различных задач. Так как машина выполняет определенный алгоритм, то к машине предъявляются требования, вытекающие из свойств алгоритмов. Во-первых, машина должна быть полностью детерминированной (вычисления должны быть точные и общепонятные) и действовать в соответствии с заданной системой правил. Во-вторых, она должна допускать ввод различных “начальных данных” (соответствующих различным задачам из данного класса задач). В-третьих, заданная система правил работы машины и класс решаемых задач должны быть согласованы так, чтобы всегда можно было “прочитать” результат работы машины. Это позволило Тьюрингу сформулировать следующий тезис, известный как Тезис Тьюринга: "Любой алгоритм можно преобразовать с Машину Тьюринга". Далее рассмотрим определение и способы построения МТ.

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

- бесконечной ленты, разделенной на ячейки, которая используется для ввода и вывода данных, а также для записи промежуточных результатов. На ленте могут записываться буквы некоторого алфавита (внешний алфавит машины Тьюринга). Удобно считать, что пустые ячейки на самом деле содержат некоторую букву алфавита А. Будем считать, что это буква a0.
- управляющей головки, способной читать символы, содержащиеся в ячейках ленты, писать символы в эти ячейки и оставаться на месте или передвигаться на одну ячейку вправо или влево.
- выделенной ячейки памяти, содержащей символ внутреннего алфавита, задающий состояние машины Тьюринга. Головка может находиться в одном из состояний (внутренний алфавит машины Тьюринга). Состояние q0 –заключительное, q1 – начальное.
- механического устройства управления, обеспечивающего перемещение головки относительно ленты.
- функциональной схемы — области памяти, содержащей команды (программу) машины Тьюринга, доступной только для чтения.

Обычно машина Тьюринга схематично изображается так:

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

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

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

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

Состояния внутренней памяти часто называют внутренними состояниями машины. Одно из этих состояний называется начальным, с него начинает работу любая машина, пусть это будет состояние q1. Еще одно специальное состояние q0 - заключительное. Символ, обозначающий заключительное состояние, будет называться стоп-символом. Наконец, если в какой-то момент времени внутренняя память машины приходит в заключительное состояние q 0, то дальнейших изменений в машине не происходит и машина называется остановившейся. Может случиться, что в машине не будет происходить никаких изменений и при каком-то другом внутреннем состоянии qi . Однако в этом случае мы будем говорить, что машина продолжает работать «вечно».

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

Работа машины состоит в том, что она из данного «состояния» по истечении одного такта работы механического устройства переходит в следующее «состояние», затем от нового состояния по истечении такта работы переходит к новому состоянию и так далее. Таким образом, если машина, имея внутреннее состояние qi и воспринимая ячейку ленты с символом ai , переводит внутреннюю память в состояние qb и одновременно содержимое воспринимаемой ячейки заменяет символом as , а управляющая головка остается на месте ( H ), сдвинется на одну ячейку вправо ( R ) или влево ( L ), то говорят, что машина выполняет команду соответственно:

Совокупность всех команд, которые может выполнять машина, называется ее программой. Так как работа машины по условию целиком определяется состоянием в данный момент ее внутренней памяти qi и состоянием воспринимаемой ячейки aj, то для каждых программа машины должна содержать одну и только одну команду, начинающуюся словом qi aj. Таким образом, программа машина с символами и состояниями содержит максимум (n+1)(m+1) команд. При этом некоторые команды являются «мертвыми», в том случае, если ни при каких входных словах в данном алфавите невозможно наступление этой конфигурации. В грамотной, с точки зрения реализации, программе таких строк быть не должно, хотя формально их наличие ошибкой не является.

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

- левее слова х и правее слова у все ячейки содержат пустой символ (Пустой символ - символ, заполняющий все клетки ленты, кроме тех из них (конечного числа), на которых записаны входные данные);
- головка машины обозревает ячейку, которая находится сразу после слова х;
- первая буква слова у записана в ячейке ленты, обозреваемой головкой машины;
- qi – состояние машины на данном шаге.

На рисунке определение конфигурации можно продемонстрировать следующим образом.

Конфигурация с начальным состоянием головки называется начальной, с заключительным состоянием – заключительной. Переход МТ из одной конфигурации в другую (например, из ) будем обозначать так: .

Действия МТ весьма разнообразны и зависят не только от программы, но и от начальной записи на ленте и начального положения головки. Любые действия машины можно назвать вычислениями.

Вычисления, производимые МТ в алфавите А – правильные, если выполняются следующие условия:

- В начальный момент машина находится в состоянии q1,а на ленте записано некоторое слово W в алфавите А и все ячейки ленты, не содержащие слово W , содержат пустой символ. Головка машины обозревает ячейку с первой буквой слова W .
- При переходе МТ в заключительное состояние q0 все ячейки левее головки содержат пустой символ. Головка находится над самой левой среди ячеек, не содержащей пустой символ (если такие имеются).

Результатом правильных вычислений МТ считается:

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

Пример 1. Построить МТ, которая осуществляет переход (Обозначение 1 n означает n подряд записанных 1).
Нетрудно понять, что внешний алфавит для такой МТ достаточно взять двухсимвольный А={0,1}, причем пустым символом будет 0. Действия МТ в данном случае сводятся к переходу к первому нулю после последовательности единиц и остановке.
Программа МТ для перехода:

Удобно представлять программу МТ в виде таблицы, строки которой помечены символами внешнего алфавита МТ, а столбцы – символами внутреннего алфавита МТ. Если МТ имеет команду , то в ячейке на пересечении строки ai и столбца qi находится выражение asHqb. Заполним таблицу, которая соответствует данной МТ.

Пошаговое исполнение программы для начальной конфигурации='011110' вы можете увидеть, перейдя по ссылке "Иллюстрация примера №1".
Иллюстрация примера №1
Пример 2. Построим МТ, которая работает следующим образом
Внешний алфавит для такой МТ достаточно взять двухсимвольный А={0,1}, причем пустым символом будет 0. Будем удалять из каждой группы единиц по одной единице до тех пор, пока одна из групп не станет пустой, причем из первой группы будем удалять из начала, а из второй из конца. Тогда если пустой стала первая группа единиц, то x < y и необходимо обнулить все оставшиеся единицы и остановиться в заключительном состоянии. Если пустой стала вторая группа единиц, то x ≥ у и необходимо обнулить все оставшиеся единицы, поставить одну единицу и остановиться в заключительном состоянии.

Программа такой МТ имеет следующий вид:

Пошаговое исполнение программы для начальной конфигурации при х=3, у=2 (начальное состояние МТ = q11 1 1 0 1 1 0) вы можете увидеть, перейдя по ссылке "Иллюстрация примера №2".
Иллюстрация примера №2

### 3. Вычисление функций на МТ

Далее будем применять МТ для правильного вычисления арифметических функций . Для вычисления будем представлять х в виде последовательности х+1 единиц. Если функция зависит от нескольких переменных, то, введя дополнительный символ (разделитель *) во внешний алфавит, будем последовательно записывать последовательности единиц, соответствующие аргументам функции, разделенные символом разделителем.

Правильным вычислением арифметической функции на МТ будем называть правильные вычисления, производимые МТ в алфавите А ={0,1} при переходе от конфигурации к конфигурации .
Пример 1. Вычислим функцию O(x)=0.
Очевидно, что действия МТ сводятся к замене всех последовательно идущих на ленте единиц нулями.
Программа вычислений :
Пошаговое исполнение программы для начальной конфигурации='1111110' вы можете увидеть, перейдя по ссылке "Иллюстрация примера №1".
Иллюстрация примера №1
Пример 2. Вычислим функцию S(x)=x+1
Для вычисления этой функции достаточно приписать слева одну единицу к последовательности единиц на ленте.
Программа вычислений:
Пошаговое исполнение программы для начальной конфигурации='0111' вы можете увидеть, перейдя по ссылке "Иллюстрация примера №2".
Иллюстрация примера №2
Пример 3. Построить машину Тьюринга для вычисления функции C(x)=S(O(x)).
Для этого будем использовать принцип суперпозииции для МТ. Суть его поясним на следующем примере. Искомую машину будем строить как суперпозицию машин, вычисляющих функции O(x)=0 и S(x)=x+1. Возьмем МТ, вычисляющие эти функции. Объединим состояния и программы этих машин. Пусть имеются две машины T1 и T2, которые вычисляют функции f1(x) и f2(x) соответственно в одном и том же алфавите. Построим новую машину Тьюринга Т следующим образом. Состояния машины T2 переобозначим так, чтобы они отличались от состояний T1. Начальное состояние q11 машины Т1 объявляем начальным состоянием q1 машины Т. Заключительное состояние q02 машины Т2 объявляем заключительным состоянием q0 машины Т. Заключительное состояние q01 машины Т1 и начальное состояние q12 машины Т2 отождествляем. Полученные команды для обеих машин объединяем в одну программу новой машины. Построенная машина Т вычисляет суперпозицию функций и называется суперпозицией машин Т1 и Т2.
В результате из двух таблиц:
получим одну:
Пример 4.Построить МТ для вычисления функции
Ранее были построены МТ для вычисления функций O(x)=0 и S(x)=x+1. Легко видеть, что исходная функция – это функция O(x), если x > 1 и функция S(x) в противном случае. Таким образом, перед вычислением нужно определить, сколько единиц находится на ленте, и в зависимости от этого переходить к вычислению функций. Для определения количества единиц на ленте будем сдвигаться по ленте вправо и на каждом сдвиге менять состояние МТ. Если обнаружили больше двух единиц, необходимо вернуться назад на начало последовательности единиц и применить МТ для вычисления функции O(x). Если обнаружили две или одну единицу, то устанавливаем головку на начале последовательности единиц и применяем МТ для вычисления функции S(x). Внутренние состояния машин для вычисления функций O(x) и S(x) пометим буквами O и S соответственно. Заключительные состояния этих машин отождествим.
Программа MT:

Пошаговое исполнение программы для двух разных начальных конфигураций вы можете увидеть, перейдя по ссылке "Иллюстрация примера №4".

- Случай №1 - начальная конфигурация='011110'; Иллюстрация примера №4 (1)
- Случай №2 - начальная конфигурация='0110'; Иллюстрация примера №4 (2)

Пример 5. Построить МТ для вычисления функции .
Чтобы правильно вычислить данную функцию, необходимо построить МТ, которая переводит конфигурацию в конфигурацию . Порядок действий для МТ можно выбрать такой. Сначала происходит движение головки вправо до появления на ленте нуля. Этот нуль разделяет аргументы на ленте. Поставим в эту ячейку вместо нуля единицу и вернемся к началу последовательности единиц. Заменим первые две единицы нулями. Тогда на ленте останется x+y+1 единиц.
Набор команд для такой MT:

Программу МТ можно изобразить в виде ориентированного графа, вершинами которого являются внутренние состояния МТ, а дуги помечены тройками из символов внешнего алфавита и символов из множества {L,R,H}.

Пошаговое исполнение программы при х=2, у=1 (начальная конфигурация='01110110') вы можете увидеть, перейдя по ссылке "Иллюстрация примера №5".
Иллюстрация примера №5

Если Вы хотите создать свои примеры МТ, либо проверить работу МТ на примерах, приведенных выше (разделы 2.2 и 2.3) на других начальных конфигурациях, то перейдите по ссылке "Создайте свою Машину Тьюринга". Эта программа также поможет Вам при выполнении контрольной работы. Сохраните архив на свой жесткий диск и запустите файл MT.exe
Создайте свою Машину Тьюринга

### 4. Алгоритмически неразрешимые задачи

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

Предварительно пронумеруем все машины Тьюринга следующим образом. Зафиксируем счетные множества символов и . Будем считать, что внешние алфавиты всех МТ берутся из множества , при этом символ принадлежит всем внешним алфавитам МТ и интерпретируется как пустой символ. Символы внутренних алфавитов всех МТ берутся из множества A, а символы a0 и q0 принадлежат внутренним алфавитам всех МТ и интерпретируются как начальное и заключительное состояния соответственно.

Каждому символу x из множества поставим в соответствие двоичную последовательность n(x) по следующему правилу:

  x | n(x)
  R | 10
  L | 100
  H | 1000
  a0 | 10000
  a1 | 1000000
  ... | ...
  ai | 102i+4
  ... | ...
  q0 | 100000
  q1 | 10000000
  ... | ...
  qj | 102j+5
  ... | ...

Очевидно, что последовательности n(x1) и n(x2) могут совпадать только тогда, когда x1=x2.
Команде МТ при сопоставим последовательность такого вида (числа здесь не перемножаются, а последовательно записаны).
Все команды МТ упорядочим в соответствие с лексикографическим порядком левых частей команд и МТ сопоставим набор нулей и единиц, состоящий из последовательно записанных двоичных наборов для каждой команды МТ. Эту последовательность назовем шифром машины Тьюринга.
Разные машины Тьюринга имеют различные шифры, при этом по шифру можно однозначно восстановить программу машины Тьюринга. Шифр машины состоит из нулей и единиц и всегда начинается с единицы. Его можно считать двоичной записью некоторого натурального числа.
Пример 1.Найдем шифр машины Тьюринга, вычисляющую функцию O(x)=0.
При условии,что а0=0, a1=1,
Программа вычислений выглядит так:

  q11 → 0Rq2
  q20 → 1Hq0
  q21 → 0Rq2
и машина имеет такой шифр:

Пусть теперь внешний алфавит некоторой машины Тьюринга содержит символы множества {a0,0,1}. На ленте записан шифр этой машины, головка МТ обозревает самую левую единицу шифра, а машина находится в начальном состоянии q1. Машина T называется самоприменимой, если после начала работы в указанной конфигурации она через конечное число шагов попадет в заключительное состояние q0, в противном случае машина T называется несамоприменимой.
Пример 2.Машина является самоприменимой, поскольку после выполнения одной команды машина попадает в заключительное состояние независимо от того, что было записано на ленте (т.е. в том числе и если был записан шифр этой машины).
Пример 3.Программа машины не содержит состояния q0, поэтому машина не может попасть в это состояние и, следовательно, является несамоприменимой.

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

Проблема самоприменимости. Пусть арифметическая функция p(x) определена следующим образом:
Существует ли машина Тьюринга T в алфавите {a0,0,1}, которая правильно вычисляет функцию p(x)?
Будем считать, что машина будет оставлять на ленте одну единицу в случае, если слово на ленте в начальной конфигурации было шифром некоторой самоприменимой машины, и будет оставлять 0, если слово на ленте в начальной конфигурации было шифром некоторой несамоприменимой машины.
Теорема. Проблема самоприменимости алгоритмически неразрешима.
Доказательство. Предположим противное, т.е. что существует машина Тьюринга T, которая решает проблему самоприменимости. Пусть {q0,q1,qm} - внутренний алфавит машины Т. Изменим программу машины Т следующим образом. В командах, содержащих символ q0, заменим q0 на qm+1. Добавим к программе команды . В результате получим новую машину Тьюринга, которую обозначим через T1.
Предположим, что в начальный момент на лентах машин T и T1 был записан шифр какой-то самоприменимой машины Тьюринга и обе машины начинают работу. Действия машин будут идентичны до тех пор, пока машина T не попадет в состояние q0, записав на ленте 1 и остановит головку над ячейкой с этой единицей. Машина T1 также напечатает на ленте единицу и поместит головку над этой ячейкой, но не остановится, перейдет в состояние qm+1 и продолжит работу, выполняя новые команды. В состояние q0 машина T1 попасть не может.
Если в начальный момент на лентах машин T и T1 был записан шифр некоторой несамоприменимой машины Тьюринга, то каждая из них попадет в заключительное состояние, выдав в качестве результата 0.
Очевидно, что каждая из машин Тьюринга в алфавите {a0,0,1} является либо самоприменимой, либо несамоприменимой. Определим к какому классу относится машина T1. Для этого на ленте запишем шифр этой машины и запустим её. Если машина T1 самоприменимая, то ее шифр является шифром самоприменимой машины, и машина будет действовать так, как описано выше, т.е. машина никогда не попадет в заключительное состояние и, следовательно, самоприменимой быть не может.
Предположим, что машина T1 несамоприменимая и ее шифр является шифром несамоприменимой машины, поэтому через конечное число шагов машина попадет в состояние q0. Это означает, что машина T1 самоприменимая, что противоречит предположению.
Теорема доказана.

Приведем еще один пример неразрешимой проблемы, которая называется проблема останова. Проблема останова заключается в том, чтобы по любой машине T и любой последовательности Sв ее внешнем алфавите узнать применима ли машина T к последовательности S, т.е. остановится ли машина T через конечное число шагов после начала работы с начальной последовательностью S на ленте. Данная проблема алгоритмически неразрешима, т.к. если бы она была разрешимой, то взяв в качестве S шифр машины T, получили бы разрешимость проблемы самоприменимости. Таким образом, проблема останова сводится к проблеме самоприменимости.

### 5. Примитивно рекурсивные функции

Часто решение поставленной задачи можно свести к вычислению некоторой целочисленной функции, определенной на множестве натуральных чисел. Этот раздел посвящен уточнению понятия алгоритма – классу частично рекурсивных функций. Этот подход к формализации алгоритма был разработан в 30-х годах прошлого столетия математиками К. Гёделем, С.К. Клини, А. Черчем.
Будем рассматривать n-арные функции на множестве наборов натуральных чисел . Такие функции назовем арифметическими функциями. Если функция определена не для каждого набора натуральных чисел, то такие функции будем называть частично определенными арифметическими функциями(ч.а.ф).
Основная идея состоит в том, чтобы получить все вычислимые функции из существенно ограниченного множества базисных функций с помощью простейших алгоритмических средств. Базисные функции выбираются так, чтобы их вычислимость была достаточно очевидна.
Определим класс функций, следующим образом. Выделим конечное множество базовых функций и операции над ними для получения новых функций. В качестве базовых (простейших) функций берут следующие функции:

- Функция следования: S(x)=x+1;
- Функция проекции: , где n – кол-во переменных, аi, 1 ≤ i ≤ n, - номер переменной, по которой берется проекция. Функция проекции – функция, равная одному из своих аргументов. Например, U23(x,y,z)=y.
- Функция нуля:O(x)=0, для всех x=0,1,...

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

Определим операции над функциями. Пусть имеются n- арная функция f и m-арные функции . Говорят, что m-арная функция получена в результате операции суперпозиции или подстановки из функций f и , если для любых .

Пусть заданы произвольные функции: n-арная функция g и n+2-арная функция h. Говорят, что n+1-арная функция f получена операцией примитивной рекурсии из функций g и h, если для любых выполнены соотношения:

В случае если n=0, то определение имеет такой вид. Говорят, что функция f(x) получена операцией примитивной рекурсии из функции h(x,y) и константы С, если для любого x ∈ N выполнены соотношения:
Предложение (свойства операций суперпозиции и примитивной рекурсии). Операции суперпозиции и примитивной рекурсии сохраняют:

1. всюду определённость функций;
2. интуитивную вычислимость функций.

Доказательство проведем для операции суперпозиции. Пусть m-арная функция получена в результате операции суперпозиции из функций f и .

1. Если все функции и f – всюду определённые, то функция g всюду определена. Функция g будет не всюду определённой, если одна из функций не всюду определена или если можно найти такие a1,...,am, что , но значение f(b1,...,bn) не определено.
2. Если каким-либо образом можно вычислять значения функций и f,то ясно,как можно вычислить значение функции g. Придадим переменным некоторые значения a1,...,am. Вычислим все f(a1,...,am), 1 ≤ i ≤ n. Получим значения . Вычисляя теперь , получим,что g(a1,...,am)=c. Таким образом, если функции и f интуитивно вычислимы, то и функция g интуитивно вычислима.

Предложение доказано.

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

1. Всякая примитивно рекурсивная функция всюду определена.
2. Если функция f получена из примитивно рекурсивных функций с применением операций суперпозиции или примитивной рекурсии, то функция f является примитивно рекурсивной функцией.
3. Все примитивно рекурсивные функции интуитивно вычислимы.

Рассмотрим несколько примеров примитивно рекурсивных функций.
Пример 1.Рассмотрим функцию g(x1,...,xm)=1 для любых . Эта функция может быть получена суперпозицией из простейших функций.
.
Таким образом, функция является примитивно рекурсивной.
Пример 2.Покажем, что функция суммы f(x,y)=x+y примитивно рекурсивна. Действительно,
,
где . Поскольку функции g и h являются примитивно рекурсивными, то и функция f является примитивно рекурсивной.
Пример 3.Покажем, что p(x,y)=x*y примитивно рекурсивна. Действительно, функция получена при помощи операции примитивной рекурсии
,
где . Поскольку функции g и h являются примитивно рекурсивными, то и функция f является примитивно рекурсивной.
Пример 4.Покажем, что функция является примитивно рекурсивной.
Представим функцию в виде примитивной рекурсии.
,
где .
Пример 5.Покажем, что функция является примитивно рекурсивной.
Представим функцию в виде примитивной рекурсии:
.
Пример 6.Покажем, что функция является примитивно рекурсивной.
Представим функцию в виде примитивной рекурсии:
.
Пример 7.Покажем, что r(x)=|x-5| является примитивно рекурсивной.
Действительно, функция получена суперпозицией функций .
Пример 8.Покажем, что функция является примитивно рекурсивной.
Представим функцию f(x) в виде суммы (сумма является примитивно рекурсивной функцией) функций f1(x), f2(x), f3(x), где
.
Теперь покажем, что каждая из функций f1(x), f2(x), f3(x) является примитивно рекурсивной, поскольку представляет собой суперпозицию примитивно рекурсивных функций.
.
Теорема.Пусть n-арная функция g примитивно рекурсивна. Тогда функции f, u, определенные следующим образом, также примитивно рекурсивны.
.
Доказательство.Из условия теоремы следует, что
.
Следовательно, функция f строится с помощью примитивной рекурсии из примитивно рекурсивных функций g(x1,...,xn-1,0) и . Поэтому функция f примитивно рекурсивна. Для функции u доказательство аналогичное.
Теорема доказана.
Пример.Положим g(x)=x. Тогда . Поскольку функция g(x)=x примитивно рекурсивная, то по предыдущей теореме функция также является примитивно рекурсивной.
Теорема.

- Если f(x1,...,xn) п.р.ф, то g(x1,...,xn,xn+1)=f(x1,...,xn) также п.р.ф. (Операция введения фиктивных переменных).
- Если f(x1,...,xn) п.р.ф, то g(x1,...,xn)=f(x2,x1,...,xn) также п.р.ф. (Операция перестановки переменных).
- Если f(x1,...,xn) п.р.ф, то g(x1,...,xn-1)=f(x1,...,xn-1,xn-1) также п.р.ф. (Операция отождествления переменных).

Доказательство.Докажем первое утверждение. Новая функция представима в виде суперпозиции п.р.ф.
Остальные утверждения доказываются аналогично.
Теорема доказана.

### 6. Частично рекурсивные функции

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

Пусть имеется арифметическая функция f(x1,...,xn) (возможно частично определенная). Пусть существует какой-то механизм вычисления этой функции, причем значение функции не определено тогда и только тогда, когда этот механизм работает бесконечно, не выдавая никакого определенного результата.

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

Чтобы найти натуральное решение y этого уравнения, будем вычислять при помощи указанного выше "механизма" последовательно значения f(x1,...,xn-1,a) для a=0,1,2,... и сравнивать с xn. Наименьшее значение a, для которого получится f(x1,...,xn-1,a)=xn, обозначим . Очевидно, что является n-арной частичной функцией, которая получена операцией минимизации из функции f(x1,...,xn).
Описанный процесс нахождения y, будет продолжаться бесконечно в следующих случаях:

- Значение f(x1,...,xn-1,y) не определено для каждого y;
- Значения f(x1,...,xn-1,i) для i=0,1,...,a-1 определены, но отличны от xn, а значение f(x1,...,xn-1,a) не определено;
- Значения f(x1,...,xn-1,y) определены для всех y=0,1,2,... и отличны от xn.

Во всех этих случаях значение считается неопределенным. В остальных случаях описанный процесс обрывается и дает наименьшее решение y = a для уравнения f(x1,...,xn-1,y) = xn.
Предложение (Свойство операции минимизации). Операция минимизации сохраняет интуитивную вычислимость функций.
Доказательство.Пусть необходимо вычислить значение функции на наборе (x1,...,xn) для некоторой интуитивно вычислимой функции f. Применим процедуру вычисления функции f на наборе (x1,...,xn-1,0). Если через конечное число шагов процедура определяет значение f(x1,...,xn-1,0) и f(x1,...,xn-1,0)=xn , то полагаем значение функции равным 0. Если же f(x1,...,xn-1,0) ≠ xn, то переходим к следующему этапу, на котором применяем процедуру вычисления функции f на наборе (x1,...,xn-1,1) и т.д.
Если на (t+1)-ом этапе вычислено значение функции f(x1,...,xn-1,t) и f(x1,...,xn-1,t)=xn, то полагаем значение функции равным t. Если на (t+1)-ом этапе вычислено значение функции f(x1,...,xn-1,t) и f(x1,...,xn-1,t) ≠ xn, то переходим к следующему этапу и т.д.
В случаях, когда на каком-то этапе процедура вычисления функции f работает бесконечно или работа процедуры завершилась безрезультатно, то считаем функцию неопределённой на наборе (x1,...,xn). А так как описанная процедура пригодна для любого набора (x1,...,xn), то, очевидно, она представляет собой алгоритм вычисления значений функции .
Предложение доказано.

Процесс вычисления , описанный выше, показывает, что если функция f интуитивно вычислима, то значение (если оно существует) может быть вычислено эффективно.

Приведем некоторые определения:

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

Pассмотрим 3 примерa общерекурсивных функций:
Пример 1.Простейшие функции S(x), O(x), Umn(x1,...,xn) для n ≥ m всюду определены, поэтому они являются общерекурсивными функциями.
Пример 2.Все примитивно рекурсивные функции являются общерекурсивными функциями.
Пример 3.Минимизируем примитивно рекурсивную функцию
Составим минимизирующее уравнение .
Найдем значения функции g(x) при различных значениях x.
При x = 0 нужно найти минимальное значение y, которое удовлетворяет условию f(y) = x = 0.

- Полагаем y = 0 и находим значение f(0) = 1. Оно не совпадает со значением x = 0.
- Полагаем y = 1 и находим значение f(1) = 0. Таким образом, такое y существует и y = 1 и g(0) = 1.

При x = 1 нужно найти минимальное значение y, которое удовлетворяет условию f(y) = x = 1.

- Полагаем y = 0 и находим значение f(0) = 1.Таким образом, такое y существует и y = 0 и g(1) = 0.

При x = 2 нужно найти минимальное значение y, которое удовлетворяет условию f(y) = x = 2.

- Полагаем y = 0 и находим значение f(0) = 1. Оно не совпадает со значением x = 2.
- Полагаем y = 1 и находим значение f(1) = 0. Оно не совпадает со значением x = 2.
- Полагаем y = 2 и находим значение f(2) = 1. Оно не совпадает со значением x = 2.
- Полагаем y = 3 и находим значение f(3)=3 - 1=1.Таким образом, такое y существует и y = 3 и g(2) = 3.

Для остальных x > 2 . Получили, что функция g(x) всюду определена и имеет следующий вид:

Далее рассмотрим 4 примерa частично рекурсивных функций:
Пример 1.Функция f(x,y)=y-x является частично рекурсивной, поскольку может быть получена с помощью операции минимизации из примитивно рекурсивной функции сложения. Действительно, . При y < x функция не определена.
Пример 2.Рассмотрим функцию, заданную уравнением:
Результат операции минимизации не определен даже для точки х=0. Действительно, при x=0 нужно найти минимальное значение z, которое удовлетворяет условию z+0+1=0. Очевидно, что среди неотрицательных целых чисел такое z не существует. Таким образом, функция f(x) является частично рекурсивной функцией, которая нигде не определена.
Пример 3.Рассмотрим функцию, заданную следующим образом:
Найдем значение f(0). При x=0 нужно найти минимальное значение z, которое удовлетворяет условию z+0=0. Очевидно, что такое z существует и z=0. Для x > 0 результат операции минимизации не определен, поскольку подбор нужного значения z никогда не будет закончен.
Пример 4.Минимизируем функцию .
Уравнение, определяющее новую функцию выглядит так:
Поскольку функция f(x) принимает только 3 значения (2,4,3), то функция g(x) определена только при этих значениях, в остальных точках значение функции g(x) не определено. Найдем значение g(2). Решая уравнение последовательной подстановкой, находим, что первое удовлетворяющее уравнению значение равно 5, т.е. g(2)=5. Аналогично определяем, что g(4)=6, g(3)=0. Таким образом,

Обозначим KПРФ – множество всех примитивно рекурсивных функций, KЧРФ – множество всех частично рекурсивных функций, KОРФ – множество всех общерекурсивных функций, а KВФ – множество всех интуитивно вычислимых функций.
Связь между этими множествами функций показывает следующее.
Предложение(о иерархии классов рекурсивных функций). .
Доказательство.Первое включение следует из определений примитивной рекурсивности и общерекурсивности функций. Существуют примеры общерекурсивных, но не примитивно рекурсивных функций (примеры не приводятся из-за сложности и громоздкости), поэтому включение строгое. Из определений частичной рекурсивности и общерекурсивности функций следует, что . Выше был приведен пример нигде не определённой частично рекурсивной функцией, а любая общерекурсивная функция является всюду определённой. Таким образом, имеет место строгое включение .
Очевидно, что , т.е. любая частично рекурсивная функция интуитивно вычислима.
Сделаем два важных замечания:

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

Предложение доказано.

### 7. Характеристики сложности алгоритмов

Различные подходы к уточнению понятия «алгоритм» позволяли изучать принципиальную возможность решения некоторой математической задачи. (Здесь речь идет об общих задачах, в которых исходные данные могут варьироваться). Однако теоретическая возможность алгоритмического решения задачи еще не гарантирует практическую реализуемость алгоритма. Поэтому необходимо ввести характеристики алгоритмов, которые бы показывали степень практической реализуемости алгоритмов. Другая причина, по которой необходимы такие характеристики, – необходимость сравнения эффективности различных алгоритмов, которые решают одну и ту же задачу.

При решении некоторой задачи P алгоритмом A обычно рассматривают такие характеристики:

- количество шагов TA(x), которое необходимо сделать алгоритму A для получения результата при использовании входных данных x. Величина (максимум берется по всем входным данным объема n) называется временной сложностью алгоритма A.
- объем памяти MA(x), необходимый для хранения всех входных и промежуточных данных в процессе выполнения алгоритма при использовании входных данных x. Величина (максимум берется по всем входным данным объема n) называется емкостной сложностью алгоритма A.

Для определения временной сложности алгоритма вместо общего числа шагов алгоритма можно также использовать количество операций определенного вида. Аналогично можно определить средние величины временной и емкостной сложности алгоритма. Сложность задачи P – это сложность наилучшего алгоритма, известного для ее решения, т.е. (минимум берется по всем алгоритмам для задачи P).

Введем понятие верхнего и нижнего порядка функции относительно другой функции. Назовем арифметическую функцию f(x) функцией одного верхнего порядка с функцией g(x), т.е. f(x)=O(g(x)), если существует такая натуральная константа C и некоторое натуральное N0, что для всех x ≥ N0.

Назовем арифметическую функцию f(x) функцией одного нижнего порядка с функцией g(x), т.е. f(x)=Ω(g(x)), если существует такая натуральная константа C и некоторое натуральное N0, что для всех x ≥ N0.

Арифметическая функция f(x) – функция одного порядка с функцией g(x), если она одного верхнего и одного нижнего порядка с функцией g(x), т.е. f(x)=O(g(x)) и f(x)=Ω(g(x)).
Пример 1.Пусть f(x)=log x и g(x)=x. Tогда существует положительная константа C, что log x ≤ C*x при x ≥ 1 , т.е. f(x)=O(g(x)).

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

Арифметические функции f(x) и g(x) называются полиномиально-связанными или полиномиально-эквивалентнтными, если существуют такие многочлены P1(x) и P2(x) и некоторое натуральное N0, что f(x) ≤ P1(g(x)) и g(x) ≤ P2(f(x)) для всех x ≥ N0.
Пример 2.Две функции f(x)=2x +3 и g(x)=x3 полиномиально связаны или эквивалентны, поскольку существуют два полинома P1(x)=x и P2(x)=x3 таких, что f(x) ≤ P1(g(x))=x3 и g(x) ≤ P2(f(x))=(2x+3)3.

Рассмотрим задачу сортировки массива из n элементов. Хорошо известны алгоритмы решения этой задачи. В качестве временной сложности алгоритма сортировки используют две характеристики – количество сравнений элементов T1 и количество пересылок элементов T2, необходимых в ходе работы алгоритма. Для метода пузырьковой сортировки показано, что T1(n)=O(n2) и T2(n)=O(n2). Однако существуют алгоритмы, например алгоритм Хоара, который имеет лучшую верхнюю оценку временной сложности, чем метод пузырьковой сортировки. В частности, T1(n)=O(n log n) и T2(n)=O(n log n). Для задачи сортировки доказана нижняя оценка временной сложности T1(n) ≥ C1 * nlogn и T2(n) ≥ C2 * nlogn при или T1(n)=Ω(nlogn), T2(n)=Ω(nlogn), т.е. для сортировки массива требуется как минимум C * nlogn сравнений и пересылок. Таким образом, сложность задачи сортировки массива из n элементов имеет порядок nlogn при .

Рассмотрим известный алгоритм сложения двух чисел столбиком. Входные данные – два числа, записанные в десятичной системе. Будем считать, что числа имеют n десятичных цифр в своем представлении. В качестве временной сложности этого алгоритма будем использовать количество операций сложений цифр, которое требуется для получения результата. Максимальное число сложений получается в случае, когда происходит перенос разряда для каждой цифры, т.е. T(n)=n + n + 1=2n + 1=O(n). Очевидно, что емкостная сложность M(n)=O(n).

Определим сложность задачи сложения двух натуральных чисел при вычислении на машине Тьюринга. На вход МТ подаются две последовательности десятичных чисел. Внешний алфавит такой МТ содержит десятичные цифры и пустой символ, т.е. A={*,0,1,2,...,9}, где * – пустой символ.
Начальная конфигурация выглядит так *q1an-1an-2...a1*bn-1bn-2...b1**. В общих чертах поведение МТ можно описать так. Сначала головка перемещается к концу второй последовательности стирает младший разряд, затем перемещается к младшему разряду первого числа и заменяет его на сумму младших разрядов и т.д.
В качестве меры временной сложности данного алгоритма будем использовать количество выполненных команд МТ для перехода из начальной конфигурации в заключительную, т.е. на ленте записан результат сложения в виде последовательности десятичных цифр и головка установлена на первой цифре. Емкостная сложность вычислений на МТ определяется количеством ячеек ленты, которые заполнены непустыми символами либо посещались головкой во время работы МТ.
Не трудно подсчитать общее количество действий и задействованных ячеек, T(n)=O(n2), M(n)=O(n). При этом для получения одного разряда результата требуется порядка n действий. Таким образом, временные сложности алгоритма сложения столбиком и алгоритма сложения на МТ полиномиально эквивалентны.
Пример 3.Арифметическая функция f(x,y)=x+y является примитивно рекурсивной, поскольку получена при помощи операции примитивной рекурсивной функции.
Действительно,
,
где h(x,y,z)=S(U33(x,y,z)). Поскольку функции g и h являются примитивно рекурсивными, то и функция f является примитивно рекурсивной. Процесс получения функции f можно представить графически в виде дерева
В качестве временной сложности можно использовать количество операций суперпозиции, примитивной рекурсии и минимизации, которые необходимы при получении функции. Количество вершин в дереве заменит емкостную сложность получения рекурсивной функции. В данном случае T=2, M=5.

### 8. Классы сложности P и NP

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

Алгоритм, обе функции сложности которого полиномиальные, называется полиномиальным алгоритмом. Такой алгоритм считается хорошим, быстрым, эффективно реализуемым. Примеры полиномиальных алгоритмов – сортировка массива чисел, алгоритм Евклида, поиск эйлерова цикла в графе, поиск остовного дерева минимального веса, умножение матриц, быстрое умножение чисел и т.д.

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

Теория сложности алгоритмов определяет классы алгоритмов по сложности. Обозначим P – класс, содержащий все полиномиальные алгоритмы; E – класс, содержащий все экспоненциальные алгоритмы. Нетрудно видеть, что .

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

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

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

Особенно хорошо применимы недетерминированные алгоритмы для задач распознавания, т.е. в качестве результата такие алгоритмы должны выдавать ответ «ДА» или «НЕТ». Недетерминированный алгоритм для задач распознавания состоит из двух стадий – стадия угадывания и стадия проверки. По заданным входным данным задачи на первой стадии происходит угадывание или генерация некоторой структуры S. Для решения задачи генерируется столько копий алгоритма, сколько существует различных структур S. Затем в каждой копии алгоритма для структуры S происходит проверка, которая выполняется обычным детерминированным алгоритмом и либо заканчивается ответом «ДА», либо ответом «НЕТ», либо продолжает работать бесконечно (два последних случая можно не различать).

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

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

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

### 9. Контрольные вопросы

1. Что такое внешний и внутренний алфавиты МТ ?
2. Что такое начальное и заключительное состояния МТ ?
3. Как выглядит команда для МТ?
4. Что такое конфигурация МТ ?
5. Сформулируйте тезис Тьюринга.
6. Какая функция называется примитивно рекурсивной? частично рекурсивной? общерекурсивной? Приведите примеры таких функций.
7. Назовите базовые функции.
8. Назовите основные операции получения ч.р.ф.
9. В чем заключается тезис Чёрча-Клини?
10. Назовите основные характеристики сложности алгоритмов.
11. Назовите основные классы сложности алгоритмов.