Задача о расписании - Автоматизированная информационная

advertisement
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РЕСПУБЛИКИ КАЗАХСТАН
ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ имени ШАКАРИМА г. СЕМЕЙ
Документ СМК 3 уровня
УМКД
УМКД 042-39. 1.ХХ/032013
УМКД
Редакция №____от_____
Учебно-методические
материалы по дисциплине
«Теория языков и автоматов»
УЧЕБНО-МЕТОДИЧЕСКИИ КОМПЛЕКС ДИСЦИПЛИНЫ
«Теория языков и автоматов»
для специальности 5В060200 – «Информатика »
УЧЕБНО-МЕТОДИЧЕСКИЕ МАТЕРИАЛЫ
Семей
2014
СОДЕРЖАНИЕ
1
2
3
4
5
Глоссарий
Лекции
Практические и лабораторные занятия
Курсовая работа (проект)
Самостоятельная работа студента
1.
ГЛОССАРИИ
Оформляется в соответствии с пунктом 6.3.1 настоящей документированной
процедуры
1) Теория алгоритмов - раздел математической логики, в котором изучаются
теоретические возможности эффективных процедур вычисления (алгоритмов) и их
приложения.
Массовая (алгоритмическая) проблема - проблема построения алгоритма,
обладающего теми или иными свойствами.
Алгоритм (алгорифм) – точное предписание, которое задает вычислительный
процесс (называемый в этом случае алгоритмическим), начинающийся с произвольного
исходного данного(из некоторой совокупности возможных дл данного алгоритма исходных
данных) и направленный на получение полностью определенного этим исходным данным
результата.
Конструктивный объект – объект формальной системы F.S = <L, D> = <A, S, Ax, R>,
где L – формальный язык, D – дедуктивные средства конструктивного процесса построения
конструктивных объектов, Ax – аксиомы(исходные данные), Ax принадлежит L, R –
отношения на множестве объектов(продукции, правила вывода, правила построения
объектов) исходных объектов.
Формальный язык – конструктивный объект, лексемы которого строятся из букв
заданного алфавита с привлечением заданной формальной грамматики.
Алгоритмический язык L = <A, S1, S2> предназначен для записи алгоритмов и при
этом
. Алгоритмический язык называется универсальным, если он содержит
алгоритмически полный набор предписаний. Задание универсального алгоритмического
языка равносильно заданию алгоритмической системы, т.е. общего способа записи
алгоритма.
Алгоритмические процессы – процессы, которые могут имитироваться на
подходяще построенной абстрактной машине, описываемой в точных математических
терминах
Тезис Тьюринга: «Для всякого алгоритма Sf в каком-либо алфавите может быть
построен тьюриноговский алгоритм, дающий при одинаковых исходных данных, те же
самые результаты, что и алгоритм Sf».
Тезис Черча-Тьюринга: «Любая теоретически разрешимая вычислительная задача
может быть решена при помощи машины Тьюринга».
Машина Тьюринга (МТ) – алгоритмически полная система побуквенной обработки
словарной информации. Эта гипотетическая машина является формой существования и
записи алгоритма.
Рекурсивное (разрешимым) множество - множество слов, для которого МТ
однозначно решает задачу принадлежности или не принадлежности данного слова языку, т.е.
машина либо переходит в состояние qz1, соответствующее заключению о принадлежности
слова языку, либо в состояние qz2 – слово не принадлежит языку.
Рекурсивно-перечислимое (частично-разрешимое) множество – такое множество,
если МТ останавливается в заключительном состоянии для лексем (слов заданного алфавита)
и «зависает» (зацикливается) или останавливается в состоянии qi
qz (безрезультатная
остановка) для непринадлежащих языку слов.
Тезис Черча: “Всякая функция, значение которой может вычисляться эффективно,
является частично-рекурсивной” (т.е. вычислимыми функциями являются частичнорекурсивные функции – функции, получаемые за конечное число шагов из простейших с
помощью суперпозиции, примитивной рекурсии и μ-оператора).
Базисные (простейшие элементарные) функции – числовые вычислимые функции
n
f : N  N , сопутствующие алгоритмы которых – одношаговые (очевидно, что это всюду
определенные рекурсивные функции)
114
Нуль-функция Z(x1, x2,…,xk)=0 – k-арная функция (оператор аннулирования Z),
соответствующий алгоритм вычисления которой: “Любой совокупности значений
аргументов xi функции Z ставится в соответствие ее значение 0”.
Функция тождества I mn (x1, x2,…,xm,…,xn)= xm ( I mn - оператор проектирования) – n-арная
функция, алгоритм вычисления которой: “Значением функции принять значение m-го
аргумента.” (m, n>0, m  n).
Функция следования  x   x '  x  1 (λ – оператор сдвига) – унарная функция, для
которой: “Значением  x  принять натуральное число, следующее за числом, являющимся
значением аргумента x”.
Оператором суперпозиции(подстановки) Snm называется операция подстановки в
функцию
от
m
переменных
m
функций
от
n
переменных.
, а сопутствующий алгоритм
которого: «Значения m –арных функций
принять за значения аргументов n–
арной функции и вычислить её значение».
Оператором примитивной рекурсии Rn[f1n-1,f2n+1,x1(n)]=fmn называется процесс
определения функции f (n+1) переменных через n-местную функцию g и (n+2)- местную
функцию h в следующем виде:
f(x1, x2, …, xn, 0)= g(x1, x2,…, xn)
f(x1, x2, …, xn, y+1)=h(x1, x2,…, xn, y, f(x1, x2, …, xn, y)),
где g и h – две различные функции соответственно n и n+2 аргументов.
Эта пара равенств называется схемой примитивной рекурсии.
Оператором минимизации 
(наименьшего числа оператора) называется
преобразование (n+1)-местной функции (в общем случае частичной)  в n-местную f, такую,
что для любых х1, х2, …хn, у равенство f(х1, х2, …хn)=у имеет место лишь в том случае, если
определены и не равны нулю значения ( х1, …, хn, 0), …, ( х1, …, хn, у-1) и при этом ( х1,
х2, …хn, у)=0
Базисные функции
для всех натуральных
n, m, где nm являются примитивно-рекурсивными;
 если g1(x1,…, xn), …gm(x1,…, xn), h(x1,…, xm) - примитивно-рекурсивные функции, то
Snm(h, g1,…, gm) - примитивно-рекурсивные функции для любых натуральных n, m;
 если g(x1,…, xn) и h(x1,…, xm, у, z) - примитивно-рекурсивные функции, то Rn(g, h) –
примитивно-рекурсивная функция;
 других примитивно-рекурсивных функций нет.
Нормальные алгорифмы U=<A, > - класс словарных алгоритмов, то есть алгоритмов
(применимых к словам некоторого алфавита А), элементарными действиями которых
являются подстановки в слова (их кортеж есть схема ).
Ассоциативное исчисление (система Туэ) U – формальная система F.S., задающая
конечно определенные ассоциативные системы (полугруппы) Ku.
Теорема (Маркова-Поста):
“Существует ассоциативное исчисление, в котором проблема распознавания
эквивалентности слов алгоритмически неразрешима”
Алгоритмически неразрешимые проблемы - массовые проблемы, для которых не
существует эффективных методов разрешения.
Теоремы Геделя:
1.
Теорема о неполноте:
Эта теорема Геделя обычно рассматривается как следующие два утверждения:
«В любой непротиворечивой формальной теории, содержащей формальную арифметику,
найдется формально неразрешимое суждение, т.е. такая замкнутая формула А, что ни А, ни
┐А не являются выводимыми в этой теории».
«Для любой непротиворечивой формальной теории, содержащей формальную арифметику,
формула
114 А, выражающая непротиворечивость теории, недоказуема в теории».
2.
Теорема о полноте
Эта теорема является утверждением о полноте классического И.П:
«Всякая предикатная формула, истинная во всех моделях выводима (по формальным
правилам классического исчисления предикатов)».
2
3
114
114
2.
ЛЕКЦИИ
Лекция №1
Тема: Введение. Предмет теории алгортмов. Примеры различных алгоритмов.
Основные требования к алгоритмам. Блок – схемы и описание алгоритма. Основные подходы
к формализации понятия алгоритма. История развития формальной теории алгоритмов.
Цель: познакомить с задачами и целями предмета, знать историю развития
формальной теории алгоритмов.
Теория
алгоритмов
–
наука,
изучающая
общие
свойства
и
закономерности алгоритмов и разнообразные формальные модели их представления. К
задачам теории алгоритмов относятся формальное доказательство алгоритмической
неразрешимости задач, асимптотический анализ сложности алгоритмов, классификация
алгоритмов в соответствии с классами сложности, разработка критериев сравнительной
оценки качества алгоритмов и т. п.
Развитие теории алгоритмов начинается с доказательства К. Гёделем теорем о
неполноте формальных систем, включающих арифметику, первая из которых была доказана
в 1931 г. Возникшее в связи с этими теоремами предположение о невозможности
алгоритмического разрешения многих математических проблем (в частности, проблемы
выводимости в исчислении предикатов) вызвало необходимость стандартизации понятия
алгоритма. Первые стандартизованные варианты этого понятия были разработаны в 30-х
годах XX века в работах А. Тьюринга, А. Чёрча и Э. Поста. Предложенные ими машина
Тьюринга, машина Поста и лямбда-исчисление Чёрча оказались эквивалентными друг другу.
Основываясь на работах Гёделя, С. Клини ввел понятие рекурсивной функции, также
оказавшееся эквивалентным вышеперечисленным.
Одним из наиболее удачных стандартизованных вариантов алгоритма является
введённое А. А. Марковым понятие нормального алгоритма. Оно было разработано десятью
годами позже работ Тьюринга, Поста, Чёрча и Клини в связи с доказательством
алгоритмической неразрешимости ряда алгебраических проблем.
В настоящее время теория алгоритмов развивается, главным образом, по трем
направлениям.

Классическая теория алгоритмов изучает проблемы формулировки задач в
терминах формальных языков, вводит понятие задачи разрешения, проводит классификацию
задач по классам сложности (P, NP и др.).

Теория асимптотического анализа алгоритмов рассматривает методы
получения асимптотических оценок ресурсоемкости или времени выполнения алгоритмов, в
частности, для рекурсивных алгоритмов. Асимптотический анализ позволяет оценить рост
потребности алгоритма в ресурсах (например, времени выполнения) с увеличением объёма
входных данных.

Теория практического анализа вычислительных алгоритмов решает задачи
получения явных функции трудоёмкости, интервального анализа функций, поиска
практических критериев качества алгоритмов, разработки методики выбора рациональных
алгоритмов.
Анализ трудоёмкости алгоритмов
Целью анализа трудоёмкости алгоритмов является нахождение оптимального
алгоритма для решения данной задачи. В качестве критерия оптимальности алгоритма
выбирается трудоемкость алгоритма, понимаемая как количество элементарных операций,
которые необходимо выполнить для решения задачи с помощью данного алгоритма.
Функцией трудоемкости называется отношение, связывающие входные данные алгоритма с
количеством элементарных операций.
Трудоёмкость алгоритмов по-разному зависит от входных данных. Для некоторых
алгоритмов трудоемкость зависит только от объёма данных, для других алгоритмов — от
114
значений данных, в некоторых случаях порядок поступления данных может влиять на
трудоемкость. Трудоёмкость многих алгоритмов может в той или иной мере зависеть от всех
перечисленных выше факторов.
Одним из упрощенных видов анализа, используемых на практике, является
асимптотический анализ алгоритмов. Целью асимптотического анализа является сравнение
затрат времени и других ресурсов различными алгоритмами, предназначенными для
решения одной и той же задачи, при больших объёмах входных данных. Используемая в
асимптотическом анализе оценка функции трудоёмкости, называемая сложностью
алгоритма, позволяет определить, как быстро растет трудоёмкость алгоритма с увеличением
объёма данных. В асимптотическом анализе алгоритмов используются обозначения,
принятые в математическом асимптотическом анализе. Ниже перечислены основные оценки
сложности.
Контрольные вопросы
1. Дать определение теории алгоритмов.
2. По каким трем направлениям развивается теория алгоритмов?
3. Что является целью анализа трудоёмкости алгоритмов?
Лекция №2
Тема: Машины Тьюринга. Внешний и внутренний алфавиты, команды, программа.
Описание работы машины Тьюринга. Вычислимые функции. Программы суммирования,
константы, копирование.
Цель: Ввести понятие машины Тьюринга, познакомить с алфавитом, командами.
Машина Тьюринга (МТ) — абстрактный исполнитель (абстрактная
вычислительная машина). Была предложена Аланом Тьюрингом в 1936 году для
формализации понятия алгоритма.
Машина
Тьюринга
является
расширением конечного
автомата и,
согласно тезису Чёрча — Тьюринга, способна имитировать все другие
исполнители (с помощью задания правил перехода), каким-либо образом
реализующие процесс пошагового вычисления, в котором каждый шаг
вычисления достаточно элементарен.
Устройство машины Тьюринга
В
состав
машины
Тьюринга
входит
бесконечная
в
обе
стороны лента (возможны
машины
Тьюринга,
которые имеют
несколько
бесконечных лент), разделённая на ячейки, и управляющее устройство,
способное находиться в одном из множества состояний. Число возможных
состояний управляющего устройства конечно и точно задано.
Управляющее устройство может перемещаться влево и вправо по ленте,
читать и записывать в ячейки ленты символы некоторого конечного алфавита.
Выделяется особый пустой символ, заполняющий все клетки ленты, кроме тех из
них (конечного числа), на которых записаны входные данные.
Управляющее устройство работает согласно правилам перехода, которые
представляют алгоритм, реализуемый данной машиной Тьюринга. Каждое правило
перехода предписывает машине, в зависимости от текущего состояния и
наблюдаемого в текущей клетке символа, записать в эту клетку новый символ,
перейти в новое состояние и переместиться на одну клетку влево или вправо.
Некоторые состояния машины Тьюринга могут быть помечены как терминальные,
и переход в любое из них означает конец работы, остановку алгоритма.
Машина
Тьюринга
называется детерминированной,
если
каждой
комбинации состояния и ленточного символа в таблице соответствует не более
одного правила. Если существует пара «ленточный символ — состояние», для
которой
существует
2
и
более
команд,
такая
машина
Тьюринга
называется недетерминированной.
114
Описание машины Тьюринга
Конкретная машина Тьюринга задаётся перечислением элементов
множества букв алфавита A, множества состояний Q и набором правил, по
которым работает машина. Они имеют вид: qiaj→qi1aj1dk (если головка находится в
состоянии qi, а в обозреваемой ячейке записана буква aj, то головка переходит в
состояние qi1, в ячейку вместо aj записывается aj1, головка делает движение dk,
которое имеет три варианта: на ячейку влево (L), на ячейку вправо (R), остаться
на месте (N)). Для каждой возможной конфигурации <qi, aj> имеется ровно одно
правило (для недетерминированной машины Тьюринга может быть большее
количество правил). Правил нет только для заключительного состояния, попав в
которое машина останавливается. Кроме того, необходимо указать конечное и
начальное состояния, начальную конфигурацию на ленте и расположение головки
машины.
Контрольные вопросы
1. Что представляет собой машина Тьюринга?
2. Что входит в состав машины Тьюринга?
3. Какая машина Тьюринга называется детерминированной.
4. Какая машина Тьюринга называется недетерминированной.
Лекция №3
Тема: Машины Тьюринга. Композиция машин Тьюринга. Организация циклов.
Вычислимость простейших функций.
Цель: познакомить с операторами композиции, знать как организовывать циклы.
С математической точки зрения машина Тьюринга — просто определенный алгоритм
для переработки слов.
Операции композиции, выполняемые над алгоритмами, позволяют образовывать
новые, более сложные алгоритмы из ранее известных простых алгоритмов. Поскольку
машина Тьюринга—алгоритм, то операции композиции применимы и к машинам Тьюринга.
Рассмотрим основные из них, а именно: произведение, возведение в степень, итерацию.
Пусть заданы машины Тьюринга Т1 и Т2, имеющие какой-то общий внешний алфавит
А = {а0, а1,..., аm} и внутренние алфавиты Q1 = {q0, q1,..., qn} и cоответственно Q2 =
{q0,q1,…,qt}. Композитом, или произведением, машины Т1 на машину T2 будем называть
машину Т с тем же внешним алфавитом А= {а0, а1,..., аm}, внутренним алфавитом Q = {q0,
q1,...,qn, qn+1, ...,qn+t} и программой, получающейся следующим образом. Во всех командах
Т1 содержащих заключительный символ q0, заменяем его на символ qn+1. Все остальные
символы в командах T1 оставляем неизменными. В командах Т2, напротив, символ q0
оставляем неизменным, но зато каждый из остальных символов заменяем символом qn+j.
Совокупность всех команд Т1 и Т2, измененных указанным способом, и будет программой
композита или произведения машин T1 и T2. Произведение машины T1 на машину Т2
обозначается через Т = T1 • T2, или Т = T1 * Т2. Таким образом, машина Т есть произведение
машин Т1 и T2, если последовательная работа этих двух машин эквивалентна работе одной
машины Т.
Термин рекурсивная
функция в теории
вычислимости используется
для
обозначения трёх классов функций

примитивно рекурсивные функции;

общерекурсивные функции;

частично рекурсивные функции.
Последние совпадают с классом вычислимых по Тьюрингу функций. Определения
этих трёх классов сильно связаны. Они были введены Куртом Гёделем с целью
формализации понятия вычислимости.
Множество частично рекурсивных функций включает в себя множество
общерекурсивных
функций, а общерекурсивные функции включают в себя примитивно
114
рекурсивные функции. Частично рекурсивные функции иногда называют просто
рекурсивными функциями.
Определение понятия примитивно рекурсивной функции является индуктивным.
Оно состоит из указания класса базовых примитивно рекурсивных функций и двух
операторов (суперпозиции и примитивной рекурсии), позволяющих строить новые
примитивно рекурсивные функции на основе уже имеющихся.
К числу базовых примитивно рекурсивных функций относятся функции следующих
трёх видов:

Нулевая функция — функция без аргументов, всегда возвращающая 0.

Функция следования одного переменного, сопоставляющая любому
натуральному числу непосредственно следующее за ним натуральное число
.

Функции
, где
, от n переменных, сопоставляющие любому
упорядоченному набору
натуральных чисел число
из этого набора.
Операторы подстановки и примитивной рекурсии определяются следующим образом:

Оператор суперпозиции (иногда — оператор подстановки). Пусть —
функция от m переменных, а
— упорядоченный набор функций
от переменных
каждая.
Тогда
результатом
суперпозиции
функций
в
функцию называется
функция от переменных,
сопоставляющая
любому
упорядоченному набору
натуральных чисел число
.

Оператор примитивной рекурсии. Пусть — функция от n переменных,
а — функция от
переменных. Тогда результатом применения оператора
примитивной рекурсии к паре функций и называется функция от
переменной
вида
;
.
В данном определении переменную можно понимать как счётчик итераций, — как
исходную функцию в начале итерационного процесса, выдающего некую
последовательность функций переменных, начинающуюся с , и — как оператор,
принимающий
на
вход
переменных
,
номер
шага
итерации
,
функцию
на данном шаге итерации, и возвращающий функцию на
следующем шаге итерации.
Множество примитивно рекурсивных функций — это минимальное множество,
содержащее все базовые функции и замкнутое относительно указанных операторов
подстановки и примитивной рекурсии.
Частично
рекурсивная
функция определяется
аналогично
примитивно
рекурсивной, только к двум операторам суперпозиции и примитивной рекурсии добавляется
ещё третий оператор — минимизации аргумента.
Общерекурсивная функция
Общерекурсивная функция — частично рекурсивная функция, определённая для
всех значений аргументов. Задача определения того, является ли частично рекурсивная
функция с данным описанием общерекурсивной или нет, алгоритмически неразрешима.
Легко понять, что любая примитивно рекурсивная функция является частично
рекурсивной, так как по определению операторы для построения частично рекурсивных
функций включают в себя операторы для построения примитивно рекурсивных функций.
Также понятно, что примитивно рекурсивная функция определена везде и поэтому
является общерекурсивной функцией (у примитивно рекурсивной функции нет повода
«зависать», так как при её построении используются операторы, определяющие везде
определённые функции).
114
Довольно сложно доказать существование и привести пример общерекурсивной
функции, не являющейся примитивно рекурсивной. Одним из популярных примеров
является функция Аккермана. Другой пример общерекурсивной функции, не являющейся
примитивно рекурсивной, строится диагональным методом Кантора из универсальной
функции для множества одноместных примитивно рекурсивных функций.
Как было показано Гёделем, частично рекурсивные функции совпадают с
множеством вычислимых функций.
Термины «частично рекурсивная функция» и «общерекурсивная функция» прижились
в силу исторических причин и по сути являются результатом неточного перевода английских
терминов partial recursive function и total recursive function, которые по смыслу более
правильно переводить как «рекурсивные функции, определенные на части множества
возможных аргументов» и «рекурсивные функции, определенные на всём множестве
возможных аргументов». Наречие «частично» относится не к прилагательному
«рекурсивные», а к области определения функции. Возможно, более правильным названием
было бы «частично определённые рекурсивные функции» и просто «везде определённые
рекурсивные функции». Но длинные названия не прижились.
Контрольные вопросы
1. Какие операции композиции применимы к машине Тьюринга?
2. Для каких трёх классов функций в теории вычислимости используется
термин рекурсивная функция?
Лекция №4-7
Тема: Рекурсивные функции. Формализация Клини. Простейшие функции.
Операторы суперпозиции и примитивной рекурсии. Класс примитивно-рекурсивных
функций. Примитивно-рекурсивные предикаты.
Цель: познакомить с теорией рекурсивных функции.
Рекурсивные функции являются одним из вариантов уточнения понятия алгоритма. В
общем, теория рекурсивных функций включает следующие классы функций:

класс примитивной рекурсивной функции (ПРФ),

класс общерекурсивной функции (ОРФ) и

класс частично рекурсивной функции (ЧРФ).
В целом теория рекурсивных функций образуется следующим образом. В начале
задается базис элементарных функций, затем определяются специальные операции над
функциями. В результате применения определенного количества операций к элементарным
функциям, строятся соответствующие классы функций: класс ПРФ, ОРФ и ЧРФ.
Примитивно рекурсивные функции (ПРФ)
Определение. Элементарными функциями называются:

функции константы
, где

функции следования
;
;
функции выбора
, где
.
Все элементарные функции - всюду определенные и алгоритмически вычислимые.
Имеется небольшое число операций над элементарными функциями, переводящими
вычислимые функции снова в вычислимые.
Основные свойства операции подстановки.
Свойство 1.
Операция подстановки сохраняет свойство всюду определенности функций, т.е. если
функция g(y1, ...,ym) и функции h1(x1, ...,xn), h2(x1, ...,xn), ..., hm(x1, ...,xn) всюду определенные
функции и функция f получается из них с помощью операции подстановки, то f также
является всюду определенной функции.

114
Доказательство.
Пусть h1, h2, ...,
hm произвольные
функции
от n переменных.
Рассмотрим
произвольный набор
. Тогда h1, h2, ..., hm будут определены в этом
наборе в силу свойства всюду определенности. Функция g будет определена на наборе (h1(x1,
...,xn), h2(x1, ...,xn), ..., hm(x1, ...,xn)) в силу свойства всюду определенности, а по определению
подстановки это и есть функция f.
Таким образом, мы доказали, что функция f определена на наборе (x1, ...,xn). Так как
мы взяли произвольный набор из множества натуральных чисел, то свойство доказано.
Свойство 2.
Операция подстановки сохраняет свойство алгоритмической вычислимости функций,
т.е. если функции g(y1, ...,ym)и h1, h2, ..., hm алгоритмически вычислимы, и f = S(q, h1, h2, ...,
hm), то существует алгоритм Af, вычисляющий функцию f.
Доказательство.
Пусть задан произвольный набор
набор
. Это означает, что этот
, гдеi=1, 2, ..., m. Далее поступаем следующим образом:
1-й шаг: применяем к набору (x1, ...,xn) алгоритм A1, вычисляющий
функцию h1. Так как функция h1 по условию алгоритмически вычислимая функция, то за
конечное число шагов алгоритм A1 дает конечный результат для функции h1.

2-й шаг: применяем к набору (x1, ...,xn) алгоритм A2, вычисляющий
функцию h2. Так как функция h2 по условию алгоритмически вычислимая функция, то через
конечное число шагов работа алгоритма Ф2завершается результативно, т.е. будут вычислено
значение функции h2 на наборе (x1, ...,xn) и т.д. Если работа всех алгоритмов A1, A2, ..., Am на
наборе (x1,
...,xn) завершилась
результативно,
т.е.
вычислены
соответствующие
значения (h1(x1, ...,xn), h2(x1, ...,xn), ..., hm(x1, ...,xn)), то переходим на следующий шаг, т.е.

m+1-й шаг: применяем алгоритм Ag, вычисляющий функцию g, к
набору (h1(x1, ...,xn), h2(x1, ...,xn), ..., hm(x1, ...,xn)). В силу свойства алгоритмически
вычислимости функции g, через конечное число шагов алгоритм Ag завершает работу на
наборе (h1(x1, ...,xn), h2(x1, ...,xn), ..., hm(x1, ...,xn)) результативно, и этот результат будем
считать значением функции f, так как по определению операции подстановки f(x1, ...,xn) =
g(h1(x1, ...,xn), h2(x1, ...,xn), ..., hm(x1, ...,xn)).
В случае, когда алгоритм Ai, где i=1, 2, ..., m не останавливается или завершает
работу нерезультативно, будем считать, что искомый алгоритм для вычисления данной
функции, т.е. функции f(x1, ...,xn), не существует.
Операция примитивной рекурсии
Пусть задана функция g(x1, ...,xn) и функция h(x1, ..., xn, y, z).
Определение. Говорят, что функция f(x1, ..., xn, y) получена из функций g(x1,
...,xn) и h(x1, ..., xn, y, z) с помощью операции примитивной рекурсии, если выполняются
следующие равенства:
f(x1,
...,
xn,
0)
=
g(x1,
...,
xn )
f(x1, ..., xn, y+1) = h(x1, ..., xn, y, f(x1, ..., xn,y))
Это определение имеет смысл, когда n<>0, при этом записывается
f(x1, ..., xn, y) = R(g(x1, ..., xn), h(x1, ..., xn, y, z))
или сокращенно f = R(g,h), где R означает операции примитивной рекурсии.
В случае, когда n=0, то операция примитивной рекурсии примет вид:

и обозначается:
114
Основные свойства операции примитивной рекурсии.
Операция примитивной рекурсии, так же как и операция подстановки, сохраняет
свойство всюду определенности и алгоритмической вычислимости.
Свойство 1.
Сохранение свойства всюду определенности функций, т.е. если g(x1, ..., xn) и h(x1, ...,
xn, y, z) всюду определенные функции, то f(x1, ..., xn, y) тоже будет всюду определенная
функция, где f = R(g, h).
Доказательство.
Берем произвольный набор (x1, ..., xn, y) и докажем, что на этом наборе
функция f определена. Доказательство проводим методом математической индукции по y.

1 шаг. Пусть y=0. Тогда по определению операции примитивной рекурсии
получаем, что f(x1, ..., xn, 0) = g(x1, ..., xn). Так как функция g всюду определенная функция по
условию, то функция f определена на наборе(x1, ..., xn, 0).

2 шаг. Предположим, что функция f определена на наборе (x1, ..., xn, y).

3 шаг. Докажем, что функция f определена на наборе (x1, ..., xn, y+1). По
определению операции примитивной рекурсии получаем, что f(x1, ..., xn, y+1) = h(x1, ..., xn, y,
f(x1, ..., xn, y)).
А функция h обладает свойством всюду определенности по условию. Следовательно,
функция f определена на наборе (x1, ..., xn, y+1). Так как функция f является арифметической
функцией, то метод математической индукции позволяет сделать вывод, что она всюду
определена.
Свойство 2.
Сохранение алгоритмической вычислимости функций, т.е., если g(x1, ..., xn) и h(x1, ...,
xn, y, z) являются алгоритмически вычислимыми функциями, то существует алгоритм Af,
вычисляющий функцию f(x1, ..., xn, y), гдеf(x1, ..., xn, y) = R(g(x1, ..., xn), h(x1, ..., xn, y, z)).
Доказательство.
Пусть
задан
произвольный
набор (x1,
...,
xn,
y).
Докажем,
что
функция f алгоритмически вычислима на этом наборе. Для доказательства поступим
следующим образом. Сначала применяем алгоритм Ag, вычисляющие функцию g(x1, ...,
xn) на набору (x1, ..., xn). В случае остановки через конечное число шагов получаем значение
функции g(x1, ..., xn) на этом наборе, равное по определению операции примитивной
рекурсии: g(x1, ..., xn) = f(x1, ..., xn, 0).
После этого используем алгоритм Ah, который вычисляет значение функции h(x1,
..., xn, y, z). Этот алгоритм последовательно применяем к следующим наборам:
.
.
.
.
Если каждый раз работа алгоритма Ah завершается результативно, то мы получаем
соответствующие значения функции h(x1, ..., xn, y, z), равные значениям функции f(x1, ..., xn,
y) (это следует из определения операции примитивной рекурсии):
.
.
.
.
А если не произошло остановки алгоритма Ag в наборе (x1, ..., xn) или не закончился
результативно алгоритмAh на одном из этапов вычисления значения функции h(x1, ..., xn, y,
z), (т.е. например, при вычислении h(x1, ..., xn, y', f(x1, ..., xn, y')) , где y' принадлежит {0, 1, 2,
..., y-1}), то переход к следующему этапу никогда не произойдет и искомый алгоритм
считается не применимым к набору (x1, ..., xn, y).
114
Определение. Примитивно рекурсивным описанием функции (ПРО) f называется
конечная последовательность функций

, удовлетворяющая следующим условиям:
последний член этой последовательности есть сама функция f, т.е.
;
для любого i=1, 2, ..., n
- есть либо элементарная функция, либо получается
из предшествующих ей функций в этой последовательности с помощью одной из операции
примитивной рекурсии или подстановки.
Определение. Функция f называется примитивно рекурсивной функцией (ПРФ),
если существует хотя бы одно ее ПРО.
Из определения следует, что всякая примитивно рекурсивная функция f имеет
несколько различных ПРО.
Например, для функции g(x,y) = x + y ПРО является последовательность следующих
функций:

Понятие предиката и логической функции. Логические операции с
предикатами.
Предикат логическая
функция,
определенная
на
некотором
множестве M,
то
есть
такая n-местная
функция p,
которая
каждому
упорядоченному набору (x1, ..., x1) из множества M сопоставляет некоторое
высказывание, обозначаемое p(x1, ..., x1). В этом случае p называется nместным предикатом на множестве M.
Из курса математической логики, нам известно, что высказывание
обычно отождествляется с его истинностным значением 1 ("истина") или 0
("ложь"). Исходя из этого, можно дать определение предиката для различной
местности.
Пусть задано произвольное множество М
.
Определение.
Одноместным
предикатом р(х) на
множестве М называется функция вида
. (5)
Двуместным предикатом p(x1,x2) на множестве М называется функция
вида
(6) и т.д.
Например, пусть в качестве множества M задано множество натуральных
чисел N. Обозначим через p(x): .
Тогда, в зависимости от значения x, логическая функция p(x) принимает
либо значение 1 ("истина") либо значение 0 ("ложь"). Действительно, при
значениях x =2, 3, 5, 7, ... , функция p(x) = 1 и в случае, когда x = 4, 6, 8, 9,
... p(x) = 0.
В данном примере в качестве объекта рассматриваются элементы из
множества натуральных чисел, а в качестве свойства взято "простое число", и это
свойство обозначено через p.
Пусть,
на
множестве
действительных
чисел
задан
двуместный
предикат p(x,y), означающие "x меньше y".
Этот предикат становится истинным или ложным высказыванием,
если x и y заменить действительными числами: "2 меньше 10", "3 меньше 5", "1,9
меньше 0,9" и т.д. Как видим, в этом случае рассматривается отношения между
элементами в множестве R. Тогда через p в данном случае обозначено отношение
между объектами, где в качестве объектов взяты x и y.
114
Таким образом, другими словами, одноместный предикат отражает наличие
или отсутствие того или иного свойства у объекта, а предикат от нескольких
переменных выражает отношение между объектами в рассматриваемом
множестве.
Контрольные вопросы
1. Какие классы включает теория рекурсивных функции?
2. Какие функции называются элементарными
3. Назовите основные свойства операции подстановки
4. Назовите основные свойства операции примитивной рекурсии
5. Что называется примитивно рекурсивным описанием функции
6. Что такое предикат
Лекция №8-9
Тема: Алгорифмы Маркова. Нормальные алгорифмы Маркова. Алфавит, слова,
простейшие процедуры. Описание работы нормального алгорифма Маркова. Цифровые
алгорифмы Маркова. Композиция алгорифмов.
Цель: Ввести понятие алгорифмы Маркова, познакомить с алфавитом.
Определение нормального алгоритма и его выполнение
В середине прошлого века выдающийся русский математик А.А. Марков ввел
понятие нормального алгоритма (алгорифма) с целью уточнения понятия "алгоритм", что
позволяет решать задачи по определению алгоритмически неразрешимых проблем. Позже
это понятие получило название нормального алгоритма Маркова (НАМ). Язык НАМ, с
одной стороны, намеренно беден, что необходимо для цели введения понятия "алгоритм".
Однако, с другой стороны, идеи НАМ положены в основу большой группы языков
программирования, получивших название языки логического программирования, которые
являются темой данного пособия.
Для определения НАМ вводится произвольный алфавит - конечное непустое
множество символов, при помощи которых описывается алгоритм и данные. В
алфавит также включается пустой символ, который мы будем обозначать греческой
буквой . Под словом понимается любая последовательность непустых
символов
алфавита либо пустой символ, который обозначает пустое слово.
Всякий НАМ определяется конечным упорядоченным множеством пар слов алфавита,
называемых подстановками . В паре слов подстановки левое (первое) слово непустое,
а правое (второе) слово может быть пустым символом. Для наглядности левое и правое
слово разделяются стрелкой. Например,
1.
2.
3.
4.
В качестве данных алгоритма берется любая непустая строка символов.
Работа НАМ состоит из последовательности совершенно однотипных шагов. Шаг работы
алгоритма может быть описан следующим образом:
1.
В упорядоченной последовательности подстановок ищем самую первую
подстановку, левое слово которой входит в строку данных.
2.
В строке данных ищем самое первое (левое) вхождение левого слова
найденной подстановки.
3.
Это
вхождение
в строке
данных заменяем
на
правое
слово
найденной подстановки (преобразование данных).
Шаг работы алгоритма повторяется до тех пор, пока
114
либо не возникнет ситуация, когда шаг не сможет быть выполнен из-за того,
что ни одна подстановка не подходит (левое слово любой подстановки уже не входит
в строку данных ) - правило остановки;

либо не будет установлено, что процесс подстановок не может остановиться.
В первом случае строка данных, получившаяся при остановке алгоритма, является
выходной (результатом) и алгоритм применим к входным данным, а во втором случае
алгоритм не применим к входным данным.
Так, определенный выше в примере нормальный алгоритм Маркова преобразует
слово
в слово
следующим образом (над стрелкой преобразования мы
пишем номер применяемойподстановки, а в преобразуемой строке подчеркиваем левое
слово применяемой подстановки ):

а при преобразовании слова abbc этот же алгоритм будет неограниченно работать, так
как имеет место цикличное повторение данных:
Таким образом, всякий нормальный алгоритм Маркова определяет функцию,
которую мы назовем нормальной (или вычислимой по Маркову), которая может быть
частичной и которая вобласти определения входному слову ставит в соответствие выходное
слово.
Возможности нормальных алгоритмов и тезис Маркова
Прежде всего рассмотрим возможности реализации арифметических операций с
помощью нормальных алгоритмов Маркова. Сначала обратим внимание на одно
обстоятельство,
связанное
с
работой
любого НАМ:
нужно
либо
вводить
дополнительное правило остановки работы нормального алгоритма (иначе в примере
увеличения числа на 1 алгоритм продолжит работу и снова будет увеличивать полученный
результат еще на 1 и т.д. неограниченное число раз), либо перед началом
работы нормального алгоритма добавлять к входной строке специальные символы, отличные
от других символов строки, которые учитываются подстановками алгоритма в начале его
работы и которые удаляются в конце работы алгоритма. Мы будем придерживаться второго
способа, как и одна из наиболее успешных реализаций нормальных алгоритмов Маркова в
виде языка программирования Рефал. В качестве добавляемого символа возьмем символ
"@".
Пример 1. Рассмотрим простейшую операцию увеличения десятичного числа на 1. В
этом случае почти всегда необходимо увеличить последнюю цифру на 1, а последняя цифра
отличается тем, что после нее идет символ "@". Поэтому первыми подстановками должны
быть подстановки типа
Но если это цифра 9, то ее нужно заменить 0 и увеличение на 1 перенести в
предыдущий разряд. Этому отвечает подстановка
Наконец, если число начинается с 9 и перед этой цифрой нужно поставить 1, то этому
будет отвечать подстановка
а если это не так, то в конце работы алгоритма символы @ надо стереть, что
выполнит подстановка
Таким образом, мы получаем следующий НАМ увеличения десятичного числа на 1:
114
Приведем работу построенного алгоритма для чисел 79 и 99:
Аналогичным образом разрабатывается нормальный алгоритм Маркова для
уменьшения числа на 1.
Пример 2. Прежде, чем перейти к другим арифметическим операциям, рассмотрим
как довольно типичный пример, используемый часто в других алгоритмах, алгоритм
копирования двоичного числа. В этом случае прежде всего исходное и скопированное числа
разделим символом "*". В разрабатываемом алгоритме мы будем копировать разряды числа
по очереди, начиная с младшего, но нужно решить 2 проблемы: как запоминать значение
символа, который мы копируем, и как запоминать место копируемого символа. Для решения
второй проблемы используем символ "!", которым мы будем определять еще не
скопированный разряд числа, после которого и стоит этот символ. Для запоминания
значения копируемого разряда мы будем образовывать для значения 0 символ "a", а для
значения 1 - символ "b". Меняя путем подстановок эти символы "a" или "b" с
последующими, мы будем передвигать разряды "a" или "b" в начало копируемого числа
(после "*"), но для того, чтобы пока не происходило копирование следующего разряда
справа, мы перед передвижением разряда временно символ "!" заменим на символ "?", а
после передвижения сделаем обратную замену. После того как все число окажется
скопированным в виде символов "a" и "b", мы заменим эти символы на 0 и 1 соответственно.
В результате нормальный алгоритм копирования двоичного числа можно определить
следующей последовательностью подстановок:
Продемонстрируем работу алгоритма для числа 10:
Для построения алгоритма сложения двух чисел можно использовать идею
уменьшения одного числа на 1 с последующим увеличением другого числа на 1 и
повторением этого до тех пор, пока уменьшаемое число не исчезнет после того, как станет
114
равным 0. Но можно использовать и более сложную идею поразрядного сложения с
переносом 1 в разряд слева. Построение этих алгоритмов, а также алгоритмов вычитания,
умножения и деления выделено для самостоятельной работы в упражнениях 2 - 9.
Приведенные примеры показывают также возможности аппарата нормальных
алгоритмов Маркова по организации ветвления и цикличных процессов вычисления. Это
показывает, что всякий алгоритм может быть нормализован т. е. задан нормальным
алгоритмом Маркова. В этом и состоит тезис Маркова, который следует понимать
как определение алгоритма.
Вместе с тем построение алгоритма в последнем приведенном примере подсказывает
следующую методику разработки НАМ:
1.
Произвести декомпозицию (разбиение на части) строящегося алгоритма. В
примере это следующие части:
1.
разделение исходного числа и копии;
2.
копирование разряда;
3.
повторение предыдущей части до полного копирования всех разрядов.
2.
Решение проблем реализации каждой части. В примере это следующие
проблемы:
1.
запоминание копируемого разряда - разряд 1 запоминается как символ "a", а
разряд 0 - как символ "b";
2.
запоминание места копируемого разряда - пометка еще не скопированного
символа дополнительным символом "!" с заменой его на символ "?" при передвижении
копируемого разряда и обратной заменой после передвижения.
3.
Если часть для реализации является сложной, то она также подвергается
декомпозиции.
4.
Сборка реализации в единый алгоритм.
Контрольные вопросы
1. Дайте определение алфавита.
2. Что понимается под словом?
3. Что называется подстановками?
4. Возможности нормальных алгоритмов.
5. Всякий ли алгоритм может быть нормализован?
Лекция № 10-11
Тема: Основы анализа алгоритмов. Классы входных данных. Сложность алгорритма.
Скорости роста. Алгоритмы вида «разделяй и властвуй». Эффективность рекурсивного
алгоритма. Метод турниров. Нижние границы. Рекуррентные соотношения на сложность
алгоритма.
Цель: ввести основные понятия алгоритма, познакомиться с видами и типами.
Алгоритм — это формально описанная вычислительная процедура, получающая
исходные данные (вход) и возвращающая результат (выход). Алгоритмы строятся для
решения тех или иных вычислительных задач, при этом они должны удовлетворять
следующим противоречащим друг другу требованиям:
1)
Быть простым для понимания, перевода в программный код и отладки;
2)
Эффективно использовать вычислительные ресурсы.
Алгоритм считают правильным (correct), если на любом допустимом входе он
заканчивает работу и выдает результат, удовлетворяющий требованиям задачи. В этом
случае говорят, что алгоритм решает (solve) данную вычислительную задачу. Неправильный
алгоритм для некоторого входа может вообще не остановиться или дать неправильный
результат. Алгоритм может быть описан различными способами, в том числе и при помощи
псевдокода, принадлежащего более высокому уровню абстракции по сравнению с языками
программирования высокого уровня (C#, Pascal, Basic и т.д.). В математическом пакете
114
MathCAD при написании кода функций, определяемых пользователем, используется
нотация, напоминающая описываемый ниже псевдокод.
Скорость роста функций
Анализируя алгоритм можно стараться найти точное количество выполняемых им
действий. Но в большинстве случаев достаточно оценить асимптотику роста времени работы
алгоритма (это делается на основе точной оценки) при стремлении размера входа к
бесконечности (asymptotic efficiency). Если у одного алгоритма асимптотика роста меньше,
чем у другого, то в большинстве случаев он будет эффективнее для всех входов, кроме,
может быть, совсем коротких.
Сравнивая некоторую функцию ƒ с некоторым множеством функций, все алгоритмы
можно сгруппировать по скорости роста. Существуют три категории:
1)
Класс функций, растущих, по крайней мере, так же быстро, как ƒ, обозначается
через Ω(ƒ) (читается как «омега большое»). Можно считать, что класс Ω(ƒ) задается
указанием свой нижней границы: все функции из него растут, по крайней мере, так же
быстро, как ƒ;
2)
Класс функций, растущих не быстрее ƒ, обозначается O. Функция ƒ образует
верхнюю границу для класса O(f)(читается как «о большое»);
3)
Класс функций, растущих с той же скоростью, что и ƒ, обозначается
Q(¦) (читается как «тэта большое»). С формальной точки зрения этот класс представляет
собой пересечение двух предыдущих классов.
Пусть время T(n) работы алгоритма на входах длины n есть Q(n2). Тогда найдутся
такие константы c1,c2 > 0 и такое число n0, что с1×n2 ≤ T(n) ≤ с2×n2 при всех n ≥ n0. Проще
говоря, начиная с некоторого размера входа n0,функциональная зависимость T(n) может быть
описана посредством n2 с точностью до константы, при этом «вилка» или диапазон
возможных значений константы, способной обеспечить полное соответствие описания
оригиналу, задается при помощи c1 и c2. Вообще, если g(n) — некоторая функция, то
запись f(n) = Q(g(n))
означает,
что
найдутся
такие c1,c2 > 0
и
такое n0,
что
0 ≤ с1×g(n) ≤ f(n) ≤ c2×g(n) для всех n ≥ n0. Запись f(n) = Q(g(n)) читается так: «эф от эн есть
тэта от же от эн».
Следует также упомянуть, что если f1(n) = Q(g(n)) и f2(n) = Q(g(n)), то отсюда не
следует f1(n) = f2(n)!
Определение Q(g(n)) предполагает, что функции f(n) и g(n) асимптотически
неотрицательны (asymptoticallynonnegative), т.е. неотрицательны для достаточно больших
значений n. Если функции f и g строго положительны, то можно исключить n0 из
определения (изменив константы c1 и c2 так, чтобы для малых n неравенство также
выполнялось).
Если f(n) = Q(g(n)) то говорят, что g(n) является асимптотически точной
оценкой (asymptotically tight bound) для f(n). На самом деле это отношение симметрично:
из f(n) = Q(g(n)) следует g(n) = Q(f(n)).
Рисунок 1.1 — Иллюстрации к определениям f(n) = Q(g(n)), f(n) = O(g(n)) и f(n) =
W(g(n))
Запись f(n) = Q(g(n)) включает в себя две оценки: верхнюю и нижнюю. Их можно
разделить. Говорят, что f(n) = O(g(n)), если найдется такая константа c > 0 и такое число n0,
что 0 ≤ f(n) ≤ c×g(n) для всех n ≥ n0. Говорят, что f(n) = W(g(n)), если найдется такая
константа c > 0 и такое число n0, что 0 ≤ c×g(n) ≤ f(n) для всех n ≥ n0. Эти записи читаются
так: «эф от эн есть о большое от же от эн», «эф от эн есть есть омега большая от же от эн».
Анализ алгоритмов; время работы в лучшем, худшем случаях и в среднем
Рассматривая различные алгоритмы решения одной и той же задачи, полезно
проанализировать, сколько вычислительных ресурсов они требуют (время работы, память), и
выбрать наиболее эффективный. Конечно, надо договориться о том, какая модель
вычислений используется. В данном учебном пособии в качестве модели по большей части
114
используется обычная однопроцессорная машина с произвольным доступом (randomaccess machine,RAM), не предусматривающая параллельного выполнения операций.
Под временем работы (running time) алгоритма будем подразумевать число
элементарных шагов, которые он выполняет. Положим, что одна строка псевдокода требует
не более чем фиксированного числа операций (если только это не словесное описание какихто сложных действий — типа «отсортировать все точки по x-координате»). Следует также
различать вызов (call) процедуры (на который уходит фиксированное число операций) и её
исполнение (execution), которое может быть долгим.
Сложность алгоритма — это величина, отражающая порядок величины требуемого
ресурса (времени или дополнительной памяти) в зависимости от размерности задачи.
Таким образом, будем различать временную T(n) и пространственную V(n) сложности
алгоритма. При рассмотрении оценок сложности, будем использовать только временную
сложность. Пространственная сложность оценивается аналогично. Самый простой способ
оценки — экспериментальный, то есть запрограммировать алгоритм и выполнить
полученную программу на нескольких задачах, оценивая время выполнения программ.
Однако, этот способ имеет ряд недостатков. Во-первых, экспериментальное
программирование — это, возможно, дорогостоящий процесс. Во-вторых, необходимо
учитывать, что на время выполнения программ влияют следующие факторы:
1)
Временная сложность алгоритма программы;
2)
Качество скомпилированного кода исполняемой программы;
3)
Машинные инструкции, используемые для выполнения программы.
Наличие второго и третьего факторов не позволяют применять типовые единицы
измерения временной сложности алгоритма (секунды, миллисекунды и т.п.), так как можно
получить самые различные оценки для одного и того же алгоритма, если использовать
разных программистов (которые программируют алгоритм каждый по-своему), разные
компиляторы и разные вычислительные машины.
Разделяй
и
властвуй (англ. divide
and
conquer) в информатике —
важная парадигма разработки алгоритмов,
заключающаяся
в рекурсивном разбиении решаемой задачи на две или более подзадачи того же
типа, но меньшего размера, и комбинировании их решений для получения ответа
к исходной задаче. Разбиения выполняются до тех пор, пока все подзадачи не
окажутся элементарными.
Корректность работы алгоритма, следующего парадигме "разделяй и
властвуй" чаще всего доказывается с помощью метода математической индукции.
А время работы можно определить решив соответствующее реккурентное
уравнение.
Типичный пример — алгоритм сортировки слиянием. Чтобы отсортировать
массив чисел по возрастанию, он разбивается на две равные части, каждая
сортируется, затем отсортированные части сливаются в одну. Эта процедура
применяется к каждой из частей до тех пор, пока сортируемая часть массива
содержит хотя бы два элемента (чтобы можно было её разбить на две
части). Время работы этого алгоритма составляет
более простые алгоритмы требуют
массива.
времени, где
Контрольные вопросы
1. Что такое алгоритм
2. Каким требованиям должны удовлетворять алгоритмы
3. Какой алгоритм считается правильным
4. Назовите категории по скорости роста
5. Что подразумевают под временем работы алгоритма.
6. Что значит сложность алгоритма
114
операций, тогда как
— размер исходного
Лекция № 12-13
Тема: Виды алгоритмов. Алгоритмы поиска и выборки, численные алгоритмы
Цель: познакомиться с алгоритмами сортировки
В словарях слово "сортировка" (sorting) определяется как "распределение, отбор по
сортам; деление на категории, сорта, разряды", однако, программисты обычно используют
это слово в более узком смысле, обозначая им перегруппировку элементов в некотором
определенном порядке. Этот процесс, пожалуй, следовало бы назвать не сортировкой, а
упорядочиванием (ordering) или ранжированием (sequencing). Однако, слово сортировка уже
прочно вошло в программистский "жаргон", поэтому мы будем в дальнейшем использовать
слово "сортировка"в узком смысле "сортировка по порядку". Значит, теперь можно
сформулировать определение "сортировка", которое будет использоваться далее.
Cортировка - это процесс перегруппировки заданного множества объектов в
некотором определённом порядке. Цель сортировки - облегчить поиск элементов.
Алгоритм сортировки — это алгоритм для упорядочения элементов в списке. В
случае, когда элемент списка имеет несколько полей, поле по которому производится
сортировка называется ключом сортировки. На практике, в качестве ключа часто выступает
число, а в остальных полях хранятся какие-либо данные, никак не влияющие на работу
алгоритма.
Пожалуй, никакая другая проблема не породила такого количества разнообразнейших
решений, как задача сортировки. Существует ли некий «универсальный», наилучший
алгоритм? Вообще говоря, нет. Однако, имея приблизительные характеристики входных
данных, можно подобрать метод, работающий оптимальным образом.
Существует множество методов сортировки, каждый из которых имеет свои
достоинства и недостатки. Алгоритмы сортировки имеют большое прикладное значение, они
интересны и сами по себе. Эта достаточно глубоко исследованная область информатики,
используется в информационно-поисковых системах, в военном и банковском деле.
Кроме общенаучного интереса к алгоритмам сортировки, в каждом алгоритме
интересно оценить и его так называемую сложность. Под сложностью понимается
максимальное число элементарных шагов алгоритма. На примерах сортировок можно
показать, как путём усложнения алгоритма, хотя под рукой и есть уже очевидные методы,
можно добиться значительного выигрыша в эффективности.
При решении задачи сортировки массивов обычно выдвигается требование
минимального использования дополнительной памяти, из которого вытекает недопустимость
использования дополнительных массивов.
Для оценки быстродействия алгоритмов различных методов сортировки, как правило,
используют два показателя:

Количество присваиваний;

Количество сравнений;
Также важными являются такие показатели, как:

Память. Ряд алгоритмов требует выделения дополнительной памяти под
временное хранение данных. При оценке используемой памяти не будет учитываться место,
которое занимает исходный массив и независящие от входной последовательности затраты,
например, на хранение кода программы.

Устойчивость. Устойчивая сортировка не меняет взаимного расположения
равных элементов. Такое свойство может быть очень полезным, если они состоят из
нескольких полей, а сортировка происходит по одному из них.

Естественность поведения. Эффективность работы метода при обработке уже
отсортированных, или частично отсортированных данных. Алгоритм ведёт себя естественно,
если учитывает эту характеристику входной последовательности и работает лучше.
Все методы сортировки можно разделить на две большие группы:

Прямые методы сортировки;
114
Улучшенные методы сортировки;
Прямые методы сортировки по принципу, лежащему в основе метода, в свою очередь
делятся на три подгруппы:

Сортировка простыми вставками (включением);

Сортировка выбором (выделением);

Сортировка обменом («пузырьковая» сортировка).
Улучшенные методы сортировки основываются на тех же принципах, что и прямые,
но используют некоторые оригинальные идеи для ускорения метода сортировки. Прямые
методы сортировки на практике используются довольно редко, так как имеют относительно
низкое быстродействие. Однако они хорошо показывают суть основанных на них
улучшенных методов. Кроме того, в некоторых случаях (как правило, при небольшой длине
массива и/или особом исходном расположении элементов массива) некоторые из прямых
методов могут даже превзойти улучшенные методы.
Анализируя алгоритм, работающий по методу вставок, мы рассматривали как
наилучший, так и наихудший случай, когда элементы массива были рассортированы в
порядке, обратном требуемому. Далее мы будем уделять основное внимание определению
только времени работы в наихудшем случае, т.е. максимальном времени работы
из всех входных данных размера п. Тому есть три причины.

Время работы алгоритма в наихудшем случае - это верхний предел этой величины для любых входных данных. Располагая этим значением, мы точно знаем, что для
выполнения алгоритма не потребуется большее количество времени. Не нужно будет делать
каких-то сложных предположений о времени работы и надеяться, что на самом деле эта
величина не будет превышена.

В некоторых алгоритмах наихудший случай встречается достаточно часто.
Например, если в базе данных происходит поиск информации, то наихудшему случаю
соответствует ситуация, когда нужная информация в базе данных отсутствует. В некоторых
поисковых приложениях поиск отсутствующей информации может происходить довольно
часто.

Характер поведения "усредненного" времени работы часто ничем не лучше
поведения времени работы для наихудшего случая. Предположим, что последовательность, к
которой применяется сортировка методом вставок, сформирована случайным образом.
Сколько времени понадобится, чтобы определить, в какое место подмассива A[1..j — 1]
следует поместить элемент А [j]? В среднем половина элементов подмассива A [1..J — 1]
меньше, чем А [j], а половина — больше его. Таким образом, в среднем нужно проверить
половину элементов подмассива A[1..j — 1] , поэтому tj приблизительно равно j/2. В
результате получается, что среднее время работы алгоритма является квадратичной
функцией от количества входных элементов, т.е. характер этой зависимости такой же, как и
для времени работы в наихудшем случае. В некоторых частных случаях нас будет
интересовать среднее время работы алгоритма, или его математическое ожидание.
Контрольные вопросы
1. Дайте определение сортировки.
2. Что является целью сортировки?
3. Что называется ключом сортировки
4. Какие показатели используются для оценки быстродействия алгоритмов различных
методов сортировки
5. Что понимают под сложностью алгоритма?

Лекция №14
Тема: Виды алгоритмов. Алгоритмы на графах: обхода, поиска минимального
остовного дерева, поиска кратчайшего пути. Параллельные алгоритмы. Жадные
приближенные алгоритмы.
114
Цель: познакомиться с алгоритмами на графах, уметь их использовать при решении
задач
Алгоритмы обхода графа
Существует много алгоритмов на графах, в основе которых лежит систематический
перебор вершин графа, такой что каждая вершина просматривается (посещается) в точности
один раз. Поэтому важной задачей является нахождение хороших методов поиска в графе.
Под обходом графов (поиском на графах) мы будем понимать процесс
систематического просмотра всех вершин графа с целью отыскания вершин,
удовлетворяющих некоторому условию.
В.Липский называет метод поиска "хорошим", если

он позволяет алгоритму решения интересующей нас задачи легко
"погрузиться" в этот метод

каждое ребро графа анализируется не более одного раза (или, что существенно
не меняет ситуации, число раз, ограниченное константой).
Поиск в глубину (depth-first search)
Один из методов систематического обхода вершин графа называется поиском в
глубину. Стратегия поиска в глубину, как следует из ее названия, состоит в том, чтобы идти
"вглубь" графа, насколько это возможно. При выполнении поиска в глубину исследуются все
ребра, выходящие из вершины, открытой последней, и покидает вершину, только когда не
остается неисследованных ребер — при этом происходит возврат в вершину, из которой
была открыта вершина v. Этот процесс продолжается до тех пор, пока не будут открыты все
вершины, достижимые из исходной. Если при этом остаются неоткрытые вершины, то одна
из них выбирается в качестве новой исходной вершины и поиск повторяется уже из нее. Этот
процесс повторяется до тех пор, пока не будут открыты все вершины.
Когда вершина v открывается в процессе сканирования списка смежности уже
открытой вершины и, процедура поиска записывает это событие, устанавливая поле
предшественника v prev[v] равным u. В отличие от поиска в ширину, где подграф
предшествования образует дерево, при поиске в глубину подграф предшествования может
состоять из нескольких деревьев, так как поиск может выполняться из нескольких
исходных вершин.
Как и в процессе выполнения поиска в ширину, вершины графа раскрашиваются в
разные цвета, свидетельствующие о их состоянии. Каждая вершина изначально белая, затем
при открытии (discover) в процессе поиска она окрашивается в серый цвет, и по завершении
(finish), когда ее список смежности полностью сканирован, она становится черной. Такая
методика гарантирует, что каждая вершина в конечном счете находится только в одном
дереве поиска в глубину.
Помимо построения леса поиска в глубину, поиск в глубину также проставляет в
вершинах метки времени (timestamp). Каждая вершина имеет две такие метки — первую d
[v], в которой указывается, когда вершина у открывается (и окрашивается в серый цвет), и
вторая — f[v], которая фиксирует момент, когда поиск завершает сканирование списка
смежности вершины у и она становится черной. Эти метки используются многими
алгоритмами и полезны при рассмотрении поведения поиска в глубину.
Поиск в ширину (breadth-first search)
Один из методов систематического обхода вершин графа называется поиском в
ширину. Он получил свое название из-за того, что при достижении во время обхода любой
вершины v далее рассматриваются все вершины, смежные с вершиной v, т.е. осуществляется
просмотр вершин "в ширину". Этот метод можно применить и к ориентированным графам.
Пусть задан граф G = (V, Е) и выделена исходная (source) вершина S. Алгоритм
поиска в ширину систематически обходит все ребра G для "открытия" всех вершин,
достижимых из s, вычисляя при этом расстояние (минимальное количество ребер) от 5 до
каждой достижимой из s вершины. Кроме того, в процессе обхода строится "дерево поиска в
114
ширину" с корнем s, содержащее все достижимые вершины. Для каждой достижимой из s
вершины v путь в дереве поиска в ширину соответствует кратчайшему (т.е. содержащему
наименьшее количество ребер) пути от s до v в G.
Для отслеживания работы алгоритма поиск в ширину раскрашивает вершины графа в
белый, серый и черный цвета. Изначально все вершины белые, и позже они могут стать
серыми, а затем черными. Когда вершина открывается (discovered) в процессе поиска, она
окрашивается. Таким образом, серые и черные вершины - это вершины, которые уже были
открыты. Если (u, v) ? Е и вершина u черного цвета, то вершина v либо серая, либо черная,
т.е. все вершины, смежные с черной, уже открыты. Серые вершины могут иметь белых
соседей, представляя собой границу между открытыми и неоткрытыми вершинами.
Алгоритмы поиска кратчайшего пути
В задаче о кратчайшем пути (shortest-paths problem) задается взвешенный
ориентированный граф G = (V, Е) с весовой функцией w : Е —> R, отображающей ребра на
их веса, значения которых выражаются действительными числами. Вес (weight) пути р = (Vo,
Vi,..., Vk) равен суммарному весу входящих в него ребер.
Вес кратчайшего пути (shortest-path weight) из вершины и в вершину v определяется
соотношением
Тогда по определению кратчайший путь (shortest path) из вершины и в вершину v —
это любой путь, вес которого удовлетворяет соотношению w (р) = delta(u, v).
Вес каждого из ребер можно интерпретировать не как расстояние, а как другую
метрику. Часто они используются для представления временных интервалов, стоимости,
штрафов, убытков или любой другой величины, которая линейно накапливается по мере
продвижения вдоль ребер графа и которую нужно свести к минимуму.
Алгоритм позволяет решить многие другие задачи, в том числе те, что перечислены
ниже.
1) Задача о кратчайшем пути в заданный пункт назначения (single-destination
shortest-paths problem). Требуется найти кратчайший путь в заданную вершину назначения
(destination vertex) t, который начинается в каждой из вершин v. Поменяв направление
каждого принадлежащего графу ребра, эту задачу можно свести к задаче о единой исходной
вершине.
2) Задача о кратчайшем пути между заданной парой вершин (single-pair shortestpaths problem). Требуется найти кратчайший путь из заданной вершины u в заданную
вершину v. Если решена задача о заданной исходной вершине u, то эта задача тоже решается.
3) Задача о кратчайшем пути между всеми парами вершин (all-pairs shortest-paths
problem). Требуется найти кратчайший путь из каждой вершины u в каждую вершину v. Эту
задачу тоже можно решить с помощью алгоритма, предназначенного для решения задачи об
одной исходной вершине, однако обычно она решается быстрее.
Поиск
минимального
остовного
дерева
(остовные
деревья
минимальной стоимости).
Пусть G — (V, Е) — связный граф, в котором каждое ребро (v, w) помечено числом
c(v, w), которое называется стоимостью ребра. Остовным деревом графа G называется
свободное дерево, содержащее все вершины V графа G. Стоимость остовного дерева
вычисляется как сумма стоимостей всех ребер, входящих в это дерево. В этом разделе мы
рассмотрим методы нахождения остовных деревьев минимальной стоимости.
114
Минимальное
остовное
дерево
связного
графа
(ребра минимального остовного дерева отдельно выделены цветом)
Приведенное дерево не единственное: удалив ребро (b, с) и заменив его ребром (a, h),
мы получим другое остовное дерево с тем же весом 37.
Существуют два алгоритма решения задачи поиска минимального остовного дерева
— алгоритм Крускала (Kruskal) и алгоритм Прима (Prim). Каждый из них легко
реализовать с помощью обычных бинарных пирамид, получив время работы О (E*lgV). При
использовании фибоначчиевых пирамид алгоритм Прима можно ускорить до O (Е + V *
lgV), что является весьма существенным ускорением при |V|<<|E|.
Оба эти алгоритма — жадные. На каждом шаге алгоритма мы выбираем один из
возможных вариантов. Жадная стратегия предполагает выбор варианта, наилучшего в
данный момент. В общем случае такая стратегия не гарантирует глобально оптимального
решения задачи, однако для задачи поиска минимального остовного дерева можно доказать,
что определенные жадные стратегии дают нам остовное дерево минимального веса.
Алгоритм Крускала
Алгоритм Крускала — алгоритм построения минимального остовного дерева
взвешенного связного неориентированного графа. Алгоритм впервые описан Джозефом
Крускалом в 1956 году.
Алгоритм Крускала находит безопасное ребро для добавления в растущий лес путем
поиска ребра (u, v) с минимальным весом среди всех ребер, соединяющих два дерева в лесу.
Обозначим два дерева, соединяемые ребром (u, v), как С1 и С2. (u, v) — безопасное для С1
ребро. Алгоритм Крускала является жадным, поскольку на каждом шаге он добавляет к
лесу ребро с минимальн возможным весом.
Реализация алгоритма Крускала напоминает алгоритм для вычисления связных
компонентов. Она использует структуру для представления непересекающихся множеств.
Каждое множество содержит вершины дерева в текущем лесу. Операция Find_Set(u)
возвращает представительный элемент множества, содержащего u. Таким образом, мы
можем определить, принадлежат ли две вершины u и v одному и тому же дереву, проверяя
равенство FindJSet(u) и Find_Set(v). Объединение деревьев выполняется при помощи
процедуры Union.
Алгоритм Прима — алгоритм построения минимального остовного дерева
взвешенного связного неориентированного графа. Алгоритм впервые был открыт в 1930 году
чешским математиком Войцехом Ярником, позже переоткрыт Робертом Примом в 1957 году,
и, независимо от них, Э. Дейкстрой в 1959 году.
Алгоритм Прима обладает тем свойством, что ребра в множестве А всегда образуют
единое дерево. Дерево начинается с произвольной корневой вершины г и растет до тех пор,
пока не охватит все вершины в V. На каждом шаге к дереву А добавляется легкое ребро,
соединяющее дерево и отдельную вершину из оставшейся части графа. Данное правило
добавляет только безопасные для А ребра; следовательно, по завершении алгоритма ребра в
114
А образуют минимальное остовное дерево. Данная стратегия является жадной, поскольку на
каждом шаге к дереву добавляется ребро, которое вносит минимально возможный вклад в
общий вес.
В качестве входных данных алгоритму передаются связный граф G и корень r
минимального остовного дерева. Все вершины G, еще не попавшие в дерево,хранятся в
очереди с приоритетом Q. Приоритет вершины v определяется значением key[v], которое
равно минимальному весу ребер, соединяющих v с вершинами минимального остова. Поле
prev[v] для вершин дерева указывает на родителя, а для вершин из очереди, указывает на
вершину дерева, в которою ведет ребро с весом key[v] (одно из таких ребер, если их
несколько).
Контрольные вопросы
1.
Что лежит в основе всех алгоритмов на графах?
2.
Что понимается под обходом графов?
3.
Что называется поиском в ширину?
4.
Что называется поиском в глубину?
Лекция №15
Тема: Виды алгоритмов. Вероятностные алгоритмы. Оценки трудоемкости
алгоритмов. Идеи современных алгоритмов
Цель: дать понятие о об оценке трудоемкости алгоритмов и о современном
состояний ТА
В настоящее время теория алгоритмов развивается, главным образом, по трем
направлениям.

Классическая теория алгоритмов изучает проблемы формулировки задач в
терминах формальных языков, вводит понятие задачи разрешения, проводит классификацию
задач по классам сложности (P, NP и др.).

Теория асимптотического анализа алгоритмов рассматривает методы
получения асимптотических оценок ресурсоемкости или времени выполнения алгоритмов, в
частности, для рекурсивных алгоритмов. Асимптотический анализ позволяет оценить рост
потребности алгоритма в ресурсах (например, времени выполнения) с увеличением объёма
входных данных.

Теория практического анализа вычислительных алгоритмов решает задачи
получения явных функции трудоёмкости, интервального анализа функций, поиска
практических критериев качества алгоритмов, разработки методики выбора рациональных
алгоритмов.
Анализ трудоёмкости алгоритмов
Основная статья: Теория сложности вычислений
Целью анализа трудоёмкости алгоритмов является нахождение оптимального
алгоритма для решения данной задачи. В качестве критерия оптимальности алгоритма
выбирается трудоемкость алгоритма, понимаемая как количество элементарных операций,
которые необходимо выполнить для решения задачи с помощью данного алгоритма.
Функцией трудоемкости называется отношение, связывающие входные данные алгоритма с
количеством элементарных операций.
Трудоёмкость алгоритмов по-разному зависит от входных данных. Для некоторых
алгоритмов трудоемкость зависит только от объёма данных, для других алгоритмов — от
значений данных, в некоторых случаях порядок поступления данных может влиять на
трудоемкость. Трудоёмкость многих алгоритмов может в той или иной мере зависеть от всех
перечисленных выше факторов.
Одним из упрощенных видов анализа, используемых на практике, является
асимптотический анализ алгоритмов. Целью асимптотического анализа является сравнение
затрат времени и других ресурсов различными алгоритмами, предназначенными для
114
решения одной и той же задачи, при больших объёмах входных данных. Используемая в
асимптотическом анализе оценка функции трудоёмкости, называемая сложностью
алгоритма, позволяет определить, как быстро растет трудоёмкость алгоритма с увеличением
объёма данных. В асимптотическом анализе алгоритмов используются обозначения,
принятые в математическом асимптотическом анализе. Ниже перечислены основные оценки
сложности.
Основной оценкой функции сложности алгоритма f(n) является оценка . Здесь n —
величина объёма данных или длина входа. Мы говорим, что оценка сложности алгоритма
если при g > 0 при n > 0 существуют положительные с1, с2, n0, такие, что:
при n > n0, иначе говоря, можно найти такие с1 и c2, что при достаточно больших n f(n)
будет заключена между
и
.
В таком случае говорят ещё, что функция g(n) является асимптотически точной
оценкой функции f(n), так как по определению функция f(n) не отличается от функции g(n) с
точностью до постоянного множителя (см. асимптотическое равенство). Например, для
метода сортировки heapsort оценка трудоёмкости составляет
то есть
Из
следует, что
.
Важно понимать, что
представляет собой не функцию, а множество
функций, описывающих рост
с точностью до постоянного множителя.
дает одновременно верхнюю и нижнюю оценки роста функции. Часто бывает
необходимо рассматривать эти оценки по отдельности. Оценка
представляет собой
верхнюю асимптотическую оценку трудоемкости алгоритма. Мы говорим, что
если
Иначе говоря, запись
означает, что f(n) принадлежит классу
функций, которые растут не быстрее, чем функция g(n) с точностью до постоянного
множителя.
Оценка задает нижнюю асимптотическую оценку роста функции f(n) и определяет
класс функций, которые растут не медленнее, чем g(n) с точностью до постоянного
множителя.
если
Например, запись
обозначает класс функций, которые растут не
медленнее, чем
, в этот класс попадают все полиномы со степенью
большей единицы, равно как и все степенные функции с основанием большим единицы.
Равенство
выполняется тогда и только тогда, когда
и
.
Асимптотический анализ алгоритмов имеет не только практическое, но и
теоретическое значение. Так, например, доказано, что все алгоритмы сортировки,
основанные на попарном сравнении элементов, отсортируют n элементов за время, не
меньшее
.
Важную роль в развитии асимптотического анализа алгоритмов сыграли A. Ахо, Дж.
Ульман, Дж. Хопкрофт.
Классы сложности
114
В рамках классической теории осуществляется классификация задач по классам
сложности (P-сложные, NP-сложные, экспоненциально сложные и др.). К классу P относятся
задачи, которые могут быть решены за время, полиномиально зависящее от объёма
исходных данных, с помощью детерминированной вычислительной машины (например,
машины Тьюринга), а к классу NP — задачи, которые могут быть решены за полиномиально
выраженное время с помощью недетерминированной вычислительной машины, то есть
машины, следующее состояние которой не всегда однозначно определяется предыдущими.
Работу такой машины можно представить как разветвляющийся на каждой неоднозначности
процесс: задача считается решённой, если хотя бы одна ветвь процесса пришла к ответу.
Другое определение класса NP: к классу NP относятся задачи, решение которых с помощью
дополнительной информации полиномиальной длины, данной нам свыше, мы можем
проверить за полиномиальное время. В частности, к классу NP относятся все задачи,
решение которых можно проверить за полиномиальное время. Класс P содержится в классе
NP. Классическим примером NP-задачи является задача о коммивояжёре.
Поскольку класс P содержится в классе NP, принадлежность той или иной задачи к
классу NP зачастую отражает наше текущее представление о способах решения данной
задачи и носит неокончательный характер. В общем случае нет оснований полагать, что для
той или иной NP-задачи не может быть найдено P-решение. Вопрос о возможной
эквивалентности классов P и NP (то есть о возможности нахождения P-решения для любой
NP-задачи) считается многими одним из основных вопросов современной теории сложности
алгоритмов. Ответ на этот вопрос не найден до сих пор. Сама постановка вопроса об
эквивалентности классов P и NP возможна благодаря введению понятия NP-полных задач.
NP-полные задачи составляют подмножество NP-задач и отличаются тем свойством, что все
NP-задачи могут быть тем или иным способом сведены к ним. Из этого следует, что если для
NP-полной задачи будет найдено P-решение, то P-решение будет найдено для всех задач
класса NP. Примером NP-полной задачи является задача о конъюнктивной форме
Исследования сложности алгоритмов позволили по-новому взглянуть на решение
многих классических математических задач и найти для ряда таких задач (умножение
многочленов и матриц, решение линейных систем уравнений и др.) решения, требующие
меньше ресурсов, нежели традиционные.
Контрольные вопросы
1. По каким направлениям в настоящее время развивается ТА?
2. Что является целью анализа ТА
3. Что называется сложностью алгоритма?
4. Что является основной оценкой функции сложности алгоритма?
3.
ПРАКТИЧЕСКИЕ И ЛАБОРАТОРНЫЕ ЗАНЯТИЯ
Лабораторная №1-2
Тема: Элементы теории алгоритмов Уточнение понятия алгоритма Универсальные
исполнители
Цель: дать понятие алгоритма и универсальных исполнителей
Уточнение понятия алгоритма. Зачем нужно определение алгоритма?
Как вы знаете, алгоритмом называют точный набор инструкций для исполнителя,
который приводит к решению задачи за конечное время. Особый интерес проявляли к
алгоритмам математики. Один из древнейших известных алгоритмов — алгоритм Евклида
для вычисления наибольшего общего делителя (НОД) двух натуральных чисел. Само слово
“алгоритм” (от имени узбекского математика IX века аль-Хорезми, которого считают
основателем алгебры) ввел в науку в XVII веке немецкий математик Г.В. Лейбниц. Долгое
время считалось, что для любой математической задачи можно найти метод (алгоритм)
114
решения, просто для ряда задач такие алгоритмы еще не найдены. Эту идею высказал еще
аль-Хорезми, такой же точки зрения придерживались и другие математики вплоть до начала
XX века. Однако, несмотря на все усилия, решить некоторые задачи не удавалось в течение
столетий. Например, безуспешно закончились многочисленные попытки найти алгоритм
доказательства правильности любой теоремы на основе заданной системы аксиом. В 1931
году австрийский математик К.Гедель доказал теорему о неполно те, смысл которой состоит
в том, что в любой достаточно сложной формальной системе, основанной на аксиомах
(например, в арифметике, где введены натуральные числа и операции сложения и
умножения), есть утверждение, которое невозможно ни доказать, ни опровергнуть в рамках
этой системы. Поэтому было высказано предположение о том, что некоторые задачи
алгоритмически неразрешимы, то есть для них в принципе не существует алгоритма
решения, и поэтому искать его бессмысленно. Чтобы строго доказать или опровергнуть эту
гипотезу, нужно было ввести математическое понятие алгоритма. “Определение”, которое
приведено в начале, часто называют интуитивным, потому что оно содержит такие
“нематематические” понятия, как “точный набор”, “инструкция”, “исполнитель”, “решение
задачи”. Эти термины невозможно записать строго, используя язык математики и логики,
поэтому для математического доказательства такое определение не подходит. Исследования
в этой области, которые начали активно проводиться в 30-х годах XX века, привели к
возникновению теории алгоритмов, которая занимается
• доказательством алгоритмической неразрешимости задач;
• анализом сложности алгоритмов;
• сравнительной оценкой качества алгоритмов.
Значительный вклад в развитие теории алгоритмов внесли математики А.Тьюринг
(Великобритания), Э.Пост (США), А.Чёрч (Великобритания), С.Клини (США) и А.А.
Марков (СССР).
Что такое алгоритм?
Первые известные алгоритмы — это правила выполнения арифметических действий с
числами. В них четко определены объекты (числа в десятичной записи) и элементарные
шаги (сложить, вычесть, перемножить два однозначных числа —вспомните таблицы
сложения и умножения). Постепенно сложность задач, которые решались с помощью
алгоритмов, увеличивалась, и понятие “шаг алгоритма” оказалось нечетким, размытым.
Например, можно ли считать элементарным шагом разложение числа на простые множители
или сложение многозначных чисел? Со временем понятие алгоритма расширилось — сейчас
мы говорим об алгоритмах для исполнителей, которые работают с текстами и другими
объектами реального мира. Однако оказалось, что все эти объекты можно тем или иным
способом закодировать в виде цепочек символов, так что любой алгоритм сводится к
преобразованию одной символьной строки в другую. Таким способом можно представить и
классические вычислительные алгоритмы — операции с цифрами. В алгоритме шахматной
игры объекты — это фигуры на доске, но их расположение легко закодировать в символьной
форме (вспомните запись шахматных партий). Поэтому можно рассматривать только
алгоритмы обработки символьных строк, а полученные результаты будут применимы к
любым алгоритмам. Как вы знаете, текст, записанный с помощью любого алфавита, всегда
можно перевести в двоичный код, поэтому, вообще говоря, достаточно рассматривать только
алгоритмы, работающие с двоичными последовательностями. Итак, про любой алгоритм
можно сказать следующее:
• алгоритм получает на вход дискретный объект (например, слово);
• алгоритм обрабатывает входной объект по шагам (дискретно), строя на каждом шаге
промежуточные дискретные объекты; этот процесс может закончиться или не закончиться;
• если выполнение алгоритма заканчивается, его результат — это объект,
построенный на последнем шаге;
• если выполнение алгоритма не заканчивается (алгоритм зацикливается), то результат
его работы при данном входе не определен.
114
Любой алгоритм рассчитан на определенного исполнителя: он должен использовать
только понятные этому исполнителю команды. Задание для исполнителя — это текст на
специальном (формальном) языке, который обычно называют программой. Поэтому можно
определить алгоритм так:
Алгоритм — это программа для некоторого исполнителя.
Напомним, что с точки зрения теории алгоритмов достаточно рассматривать только
алгоритмы, работающие с цепочками символов, которые называют словами.
Каждый алгоритм задает (вычисляет) функцию, которая преобразует входное слово в
результат (выходное слово). Такая функция может быть не определена для некоторых
входных слов, если алгоритм зацикливается.
Функция, заданная алгоритмом, может быть нигде не определена. Например,
алгоритм
нц пока да
кц
выходит в бесконечный цикл при любом входном слове.
Алгоритмы называются эквивалентными, если они задают одну и ту же функцию. То
есть при любом входном слове оба алгоритма должны приводить к одному и тому же
результату или зацикливаться (оба алгоритма не дают никакого результата). Например,
следующие алгоритмы для выбора минимального из значений переменных a и b
эквивалентны:
если a < b то
M:= a
иначе
M:= b
все
M:= b
если a < b то
M:= a
все
Универсальные исполнители
Как мы уже видели, понятие алгоритма оказывается “привязанным” к его
исполнителю и некоторому языку программирования. Это не позволяет определить алгоритм
как математический объект. Поэтому возникла идея попытаться построить универсального
исполнителя.
Универсальный исполнитель — это исполнитель, для которого можно построить
алгоритм, эквивалентный любому алгоритму для любого другого исполнителя. Такого
исполнителя можно было бы использовать для доказательства разрешимости или
неразрешимости задач. Если удается построить алгоритм решения задачи для
универсального исполнителя, то задача разрешима. Если доказано, что алгоритма не
существует, то задача неразрешима. Система команд такого исполнителя должна быть как
можно проще — так его будет легче использовать в доказательствах. В середине XX века
было предложено (разными учеными, независимо друг от друга) несколько исполнителей,
претендующих на роль универсальных (они будут рассмотрены далее), причем в теории
алгоритмов доказано, что все они эквивалентны друг другу, то есть алгоритм, который
можно
запрограммировать
для
одного
универсального
исполнителя,
можно
запрограммировать также и для остальных. Как же связан универсальный исполнитель с
проблемой строгого определения алгоритма? Любой алгоритм может быть представлен как
программа для универсального исполнителя. Это основная идея теории алгоритмов. Строго
доказать это утверждение невозможно, потому что здесь используется интуитивное понятие
“алгоритм”. Как мы увидим, каждый универсальный исполнитель описывается с помощью
математических терминов, поэтому на его основе можно дать строгое определение
алгоритма:
114
Алгоритм — это программа для универсального исполнителя.
Универсальный исполнитель — это некоторая модель вычислений, которая задает
способ описания алгоритмов и их выполнения. Модель вычисления должна содержать
• “процессор”, задающий систему команд и способ их выполнения;
• “память”, определяющую способ хранения данных;
• язык программирования (способ записи программ);
• способ ввода данных (чтения входного слова);
• способ вывода слова-результата.
Все универсальные исполнители эквивалентны по определению. Это значит, что для
любого алгоритма для одного универсального исполнителя можно построить эквивалентный
алгоритм для другого универсального исполнителя. Поэтому последнее приведенное
определение алгоритма фактически не зависит от конкретного исполнителя.
Практическое задание
1. Составить конспект по теме, ответить письменно на вопросы.
2. Построить блок-схему алгоритма для вычисления. Результат вывести на экран
1.Дана функция y  y  ax 2  bx ; Вычислить значение у при заданном a, b и x.
2.Построить блок-схему алгоритма для вычисления u 
a x  sin x
b
, при условии, что в
x0. Результат вывести на экран.
3.Построить блок-схему алгоритма для вывода длины двух катетов прямоугольного
треугольника и нахождения длины гипотенузы и площади треугольника (использовать
теорему Пифагора).
4.Построить блок-схему алгоритма для вычисления
вывести на экран.
R  sin x  cos x 2 . Результат
x2
2 . При условии, что x  0 .
5.Построить блок-схему алгоритма для вычисления Y 
x2
x
3
Результат вывести на экран.
6.Построить блок-схему алгоритма для вычисления длины окружностей с радиусами R1
и R 2 и одним центром, а также площади кольца, образованного этими окружностями.
7.Построить блок-схему алгоритма для вычисления: Y  x  sin( x)  a. Результат вывести
на экран.
x  a sin x
8.Построить блок-схему алгоритма для вычисления: U 
при условии, что
ax
a  x . Результат вывести на экран.
9.Построить блок-схему алгоритма для нахождения объема куба и площади его сторон по
произвольному ребру куба a .
A 2
Z
2
2
 AZ результат
10. Построить блок-схему алгоритма для вычисления: U  AZ 
13.61
вывести на экран.
b
F  a cos 2  sin x  c
11. Построить блок-схему алгоритма для вычисления:
, при
a
5x 
условии, что а0. Результат вывести на экран.
12. Построить блок-схему алгоритма для вычисления объема куба и общей площади его
граней, если длина ребра куба равна а.
114
13. Построить блок-схему алгоритма для вычисления.
 2
ax , для x  0,
F= 
(ax  b) 2 в противном случае

14. Ввести два числа, и найти какое из них минимальное, какое максимальное.
xy sin x
.
15. Вычислить: REZ=
cos x  y 
16. Задача 4. Вывести три числа и удвоить значение тех из них, которые положительные.
17. Ввести четыре числа. Найти среди них минимальное и максимальное.
5 x 2  sin x
18. Построить блок-схему алгоритма для вычисления U 
.
cos x
19. Построить блок-схему алгоритма для вычисления

ax  sin, при x  0
F 
(a  b) x  ab, в противном случае

20. Ввести два числа R1 и R 2 , являющихся радиусом концентрических окружностей и
выяснить, какая из окружностей больше.
21. Ввести три числа и найти площади квадратов с такими сторонами, вывести площади
квадратов в порядке возрастания.
22. Ввести четыре числа и найти сумму и произведение двух из них, не являющихся ни
минимальным, ни максимальным.
(a  b) 2 sin c
23. Построить блок-схему алгоритма для вычисления: R 
d
24. Построить блок-схему алгоритма для ввода двух чисел a и b . Если a < b , оба числа
возвести в квадрат, если a  b - оставить их без изменения. Если a  b , возвести эти числа
в куб.
25. Построить блок-схему алгоритма для вычисления Z  x  y - если x  0 , Z  x  y  1 в противном случае
26. Ввести три числа, возвести в квадрат те из них, значения которых отрицательны.
27. Ввести 4 числа a , b , c , d . Найти среди них минимальное и вывести его на экран.
ax 2  sin x
R
28. Построить блок-схему алгоритма для вычисления.
sin( x  a) 2
29.Ввести два числа а1 и а2 если ни одно из них не равно 0 (а1а20), то найти их
произведение, противном случае вывести то число, которое 0.
30.Ввести три числа и если среди них есть хотя бы одно неотрицательное – найти их
алгебраическую сумму.
Контрольные вопросы
1. Зачем понадобилось уточнять понятие “алгоритм”?
2. Какие задачи рассматриваются в теории алгоритмов?
3. Почему можно ограничиться алгоритмами обработки символьных строк? Можно ли
рассматривать только алгоритмы для преобразования двоичных кодов?
4. Как вы понимаете утверждение “алгоритм задает некоторую функцию”?
5. Как связаны понятия “алгоритм” и “исполнитель”?
6. Что такое программа?
7. В каком случае говорят, что два алгоритма эквивалентны?
8. Что такое универсальный исполнитель?
9. Сравните интуитивное и строгое понятия алгоритма.
114
Лабораторная №3-5
Тема: Машина Тьюринга
Цель: развитие навыков по решению задач на машине Тьюринга
Машина Тьюринга — это строгое математическое построение, математический
аппарат аналогичный, например, аппарату дифференциальных уравнений), созданный для
решения определенных задач. Этот математический аппарат был назван “машиной” по той
причине, что по описанию его составляющих частей и функционированию он похож на
вычислительную машину. Принципиальное отличие машины Тьюринга от вычислительных
машин состоит в том, что ее запоминающее устройство представляет собой бесконечную
ленту: у реальных вычислительных машин запоминающее устройство может быть как
угодно большим, но обязательно конечным. Машину Тьюринга нельзя реализовать именно
из-за бесконечности ее ленты. В этом смысле она мощнее любой вычислительной машины. В
каждой машине Тьюринга есть две части: 1) неограниченная в обе стороны лента,
разделенная на ячейки; 2) автомат (головка для считывания/записи, управляемая
программой).
С каждой машиной Тьюринга связаны два конечных алфавита: алфавит входных
символов
и алфавит состояний
(С разными
машинами Тьюринга могут быть связаны разные алфавиты A и Q.) Состояние q0 называется
пассивным. Считается, что если машина попала в это состояние, то она закончила свою
работу. Состояние q1 называется начальным. Находясь в этом состоянии, машина начинает
свою работу. Входное слово размещается на ленте по одной букве в расположенных подряд
ячейках. Слева и справа от входного слова находятся только пустые ячейки (в алфавит А
всегда входит пустая буква а0 — признак того, что ячейка пуста). Автомат может двигаться
вдоль ленты влево или вправо, читать содержимое ячеек и записывать в ячейки буквы. Ниже
схематично нарисована машина Тьюринга, автомат которой обозревает первую ячейку с
данными.
Автомат каждый раз “видит” только одну ячейку. В зависимости от того, какую букву
ai он видит, а также в зависимости от своего состояния qj автомат может выполнять
следующие действия:
• записать новую букву в обозреваемую ячейку;
• выполнить сдвиг по ленте на одну ячейку вправо/влево или остаться неподвижным;
• перейти в новое состояние.
То есть у машины Тьюринга есть три вида операций. Каждый раз для очередной пары
(qj, ai) машина Тьюринга выполняет команду, состоящую из трех операций с определенными
параметрами.
Программа для машины Тьюринга представляет собой таблицу, в каждой клетке
которой записана команда.
114
Клетка (qj, ai) определяется двумя параметрами — символом алфавита и состоянием
машины. Команда представляет собой указание: куда передвинуть головку чтения/записи,
какой символ записать в текущую ячейку, в какое состояние перейти машине. Для
обозначения направления движения автомата используем одну из трех букв: “Л” (влево), “П”
(вправо) или “Н” (неподвижен). После выполнения автоматом очередной команды он
переходит в состояние qm (которое может в частном случае совпадать с прежним состоянием
qj). Следующую команду нужно искать в m-й строке таблицы на пересечении со столбцом al
(букву al автомат видит после сдвига). Договоримся, что когда лента содержит входное
слово, то автомат находится против какой-то ячейки в состоянии q1. В процессе работы
автомат будет перескакивать из одной клетки программы (таблицы) в другую, пока не
дойдет до клетки, в которой записано, что автомат должен перейти в состояние q 0. Эти
клетки называются клетками останова. Дойдя до любой такой клетки, машина Тьюринга
останавливается. Несмотря на свое простое устройство, машина Тьюринга может выполнять
все возможные преобразования слов, реализуя тем самым все возможные алгоритмы.
Пример. Требуется построить машину Тьюринга, которая прибавляет единицу к
числу на ленте. Входное слово состоит из цифр целого десятичного числа, записанных в
последовательные ячейки на ленте. В начальный момент машина находится против самой
правой цифры числа.
Решение. Машина должна прибавить единицу к последней цифре числа. Если
последняя цифра равна 9, то ее заменить на 0 и прибавить единицу к предыдущей цифре.
Программа для данной машины Тьюринга может выглядеть так:
В этой машине Тьюринга q1 — состояние изменения цифры, q0 — состояние останова.
Если в состоянии q1 автомат видит цифру 0..8, то он заменяет ее на 1..9 соответственно и
переходит в состояние q0, т.е. машина останавливается. Если же он видит цифру 9, то
заменяет ее на 0, сдвигается влево, оставаясь в состоянии q1. Так продолжается до тех пор,
пока автомат не встретит цифру меньше 9. Если же все цифры были равны 9, то он заменит
их нулями, запишет 0 на месте старшей цифры, сдвинется влево и в пустой клетке запишет 1.
Затем перейдет в состояние q0, т.е. остановится.
Практические задания
1. На ленте машины Тьюринга содержится последовательность символов “+”.
Напишите программу для машины Тьюринга, которая каждый второй символ “+” заменит на
“–”. Замена начинается с правого конца последовательности. Автомат в состоянии q1
обозревает один из символов указанной последовательности. Кроме самой программытаблицы, описать словами, что выполняется машиной в каждом состоянии.
2. Дано число n в восьмеричной системе счисления. Разработать машину Тьюринга,
которая увеличивала бы заданное число n на 1. Автомат в состоянии q1 обозревает некую
114
цифру входного слова. Кроме самой программы-таблицы, описать словами, что выполняется
машиной в каждом состоянии.
3. Дана десятичная запись натурального числа n > 1. Разработать машину Тьюринга,
которая уменьшала бы заданное число n на 1. Автомат в состоянии q1 обозревает правую
цифру числа. Кроме самой программы-таблицы, описать словами, что выполняется машиной
в каждом состоянии.
4. Дано натуральное число n > 1. Разработать машину Тьюринга, которая уменьшала
бы заданное число n на 1, при этом в выходном слове старшая цифра не должна быть 0.
Например, если входным словом было “100”, то выходным словом должно быть “99”, а не
“099”. Автомат в состоянии q1 обозревает правую цифру числа. Кроме самой программытаблицы, описать словами, что выполняется машиной в каждом состоянии.
5. Дан массив из открывающих и закрывающих скобок. Построить машину Тьюринга,
которая удаляла бы пары взаимных скобок, т.е. расположенных подряд “( )”. Например, дано
“) ( ( ) ( ( )”, надо получить “) . . . ( ( ”. Автомат в состоянии q 1 обозревает крайний левый
символ строки. Кроме самой программы-таблицы, описать словами, что выполняется
машиной в каждом состоянии.
6. Дана строка из букв “a” и “b”. Разработать машину Тьюринга, которая переместит
все буквы “a” в левую, а буквы “b” — в правую части строки. Автомат в состоянии q1
обозревает крайний левый символ строки. Кроме самой программы-таблицы, описать
словами, что выполняется машиной в каждом состоянии.
7. На ленте машины Тьюринга находится число, записанное в десятичной системе
счисления. Умножить это число на 2. Автомат в состоянии q1 обозревает крайнюю левую
цифру числа. Кроме самой программы-таблицы, описать словами, что выполняется машиной
в каждом состоянии.
8. Даны два натуральных числа m и n, представленные в унарной системе счисления.
Соответствующие наборы символов “|” разделены пустой клеткой. Автомат в состоянии q1
обозревает самый правый символ входной последовательности. Разработать машину
Тьюринга, которая на ленте оставит сумму чисел m и n. Кроме самой программы-таблицы,
описать словами, что выполняется машиной в каждом состоянии.
9. Даны два натуральных числа m и n, представленных в унарной системе счисления.
Соответствующие наборы символов “|” разделены пустой клеткой. Автомат в состоянии q1
обозревает самый правый символ входной последовательности. Разработать машину
Тьюринга, которая на ленте оставит разность чисел m и n. Известно, что m > n. Кроме самой
программы-таблицы, описать словами, что выполняется машиной в каждом состоянии.
10. На ленте машины Тьюринга находится десятичное число. Определить, делится ли
это число на 5 без остатка. Если делится, то записать справа от числа слово “да”, иначе —
“нет”. Автомат обозревает некую цифру входного числа. Кроме самой программы-таблицы,
описать словами, что выполняется машиной в каждом состоянии.
Контрольные вопросы
1. Зачем понадобилось уточнять понятие “алгоритм”?
2. Какие задачи рассматриваются в теории алгоритмов?
3. Почему можно ограничиться алгоритмами обработки символьных строк? Можно ли
рассматривать только алгоритмы для преобразования двоичных кодов?
4. Как вы понимаете утверждение “алгоритм задает некоторую функцию”?
5. Как связаны понятия “алгоритм” и “исполнитель”?
6. Что такое программа?
7. В каком случае говорят, что два алгоритма эквивалентны?
8. Что такое универсальный исполнитель?
9. Сравните интуитивное и строгое понятия алгоритма.
10. Опишите устройство и систему программирования машины Тьюринга.
11. Что такое состояние машины Тьюринга?
12. Сопоставьте устройство машины Тьюринга
114
с устройством компьютера. Какие устройства машины Тьюринга выполняют те же
функции, что и аналогичные устройства компьютера?
13. В чем особенность состояний q0 и q1 машины Тьюринга?
14. По какому принципу можно построить программу для машины Тьюринга, которая
последовательно выполняет операции А и Б?
Лабораторная №6-8
Тема: Машина Поста
Цель: развитие навыков по решению задач на машине Поста.
Практически одновременно с Тьюрингом (в том же 1936 году) и независимо от него
американский математик Э.Л. Пост предложил еще более простого универсального
исполнителя, который позднее получил название “машина Поста”. Лента в машине Поста
(так же, как и в машине Тьюринга) бесконечна и разбита на ячейки. Каждая ячейка может
содержать метку (быть отмечена) или не содержать ее (пустая ячейка). Таким образом, Пост
сократил алфавит всего до двух цифр. Это допустимо, потому что любые данные можно
перекодировать в двоичный код, сопоставив каждой букве исходного алфавита уникальную
последовательность нулей и единиц.
Кроме того, алгоритм работы машины Поста задается не в виде таблицы, а как
программа для универсального исполнителя. Система команд машины Поста содержит
только 6 команд:
“←” — переместить каретку на одну ячейку влево;
“→” — переместить каретку на одну ячейку вправо;
“0” — стереть метку в рабочей ячейке (записать 0);
“1” — поставить метку в рабочей ячейке (записать 1);
“? n0,n1” — если в рабочей ячейке нет метки, перейти к строке n0, иначе перейти к
строке n1;
“стоп” — остановить машину.
Попытка стереть метку там, где ее нет, или поставить метку повторно считается
ошибкой, и машина аварийно останавливается. Все строки в программе нумеруются по
порядку, это необходимо для работы команды ветвления (? n0,n1). С помощью этой команды
можно также строить циклы, как с предусловием, так и с постусловием. Например,
следующая программа перемещает каретку влево до первой отмеченной ячейки:
1. ←
2. ? 1,3
3. стоп
После команд “←”, “→”, “0” и “1” можно указать номер строки, на которую нужно
перейти сразу после выполнения этой команды. Например, команда ← 3 означает
“переместить каретку влево и перейти на строку 3”. При работе с машиной Поста числа
обычно записывают в унарной (единичной) системе счисления, в виде непрерывной цепочки
меток нужной длины (вспомните счетные палочки в младшей школе).
Например, на ленте, показанной на рисунке выше, записано число 4. Пост
предположил, что любой алгоритм может быть записан как программа для машины Поста.
В теории алгоритмов доказано, что машины Поста и Тьюринга одинаковы по своим
возможностям. Это значит, что круг задач, который они решают, тоже одинаков.
Практические задания
3. Что делают следующие программы для машины Поста:
114
Как будет работать каждая из программ при различных начальных состояниях ленты?
4. Напишите программу для машины Поста, которая увеличивает (уменьшает)
число в единичной системе счисления на единицу. Каретка расположена слева
от числа.
5. Напишите программу для машины Поста, которая складывает два числа в
единичной системе счисления. Каретка расположена над пробелом,
разделяющим эти числа на ленте.
6. Напишите программу для машины Поста, которая складывает два числа в
единичной системе счисления. Каретка расположена над пробелом,
разделяющим эти числа на ленте.
7. На ленте находятся два массива меток, разделенных пробелом. Пусть в первом
из них А меток, а во втором В меток. Каретка стоит на самой правой метке
первого числа. Сформировать справа от них через пустую секцию
результирующий массив, в котором А+В меток.
8. Определить, какая из двух групп, разделенных пустой секцией, больше, и
удалить из нее самую правую метку. Каретка стоит на самой правой метке
первого числа.
9. Деление с остатком. На ленте записаны в унарной системе делитель, а потом
через пробел - делимое (возможно, нуль), Каретка стоит на первом знаке
делителя.
10.В конце работы слева от каретки - частное, справа - остаток от деления.
11.Скопировать число, записанное в унарной системе счисления. Каретка стоит на
самой левой метке, входящей в число.
12.Сложить несколько натуральных чисел. Каждое число кодируется как
последовательность расположенных рядом отметок (в унарной системе
счисления). Числа отделены друг от друга пробелами. Каретка находится
справа от первого числа.
Контрольные вопросы
1. Сравните машины Тьюринга и Поста.
2. Зачем нумеруются строки в программе для машины Поста?
Лабораторная №9-11
Тема: Нормальные алгорифмы Маркова
Цель: развитие навыков по решению задач.
Советский математик А.А. Марков, который в середине XX века изучал разрешимость
некоторых задач алгебры, предложил новую модель вычислений, которую он назвал
нормальными алгорифмами. Нормальные алгорифмы Маркова (НАМ) — это строгая
математическая форма записи алгоритмов обработки символьных строк, которую можно
использовать для доказательства разрешимости или неразрешимости различных задач.
Марков предположил, что любой алгоритм можно записать как НАМ.
В отличие от машин Тьюринга и Поста НАМ — это “чистый” алгоритм, который не
связан ни с каким “аппаратным обеспечением” (лентой, кареткой и т.п.).
НАМ преобразует одно слово (цепочку символов некоторого алфавита) в другое и
задается алфавитом и системой подстановок. Заметьте, что в жизни мы нередко применяем
такие замены. Например, при умножении в столбик мы не вычисляем каждый раз
произведение 7 × 8, а просто помним, что оно равно 56.
114
Пусть алфавит НАМ — это русские буквы, и задана система подстановок
а→н
ух → ло
м→с
Применим эту систему подстановок к начальному слову “муха”. Подстановки нужно
просматривать по порядку, начиная с первой. Первая подстановка означает “если в слове
есть буквы а, заменить первую букву а на букву н”. В слове муха есть буква “а”, поэтому
заменяем ее на “н”. Получается “мухн”. Начинаем просмотр подстановок сначала. Букв “а”
больше нет, поэтому переходим ко второй подстановке. Сочетание “ух” есть в слове “мухн”,
поэтому вторая подстановка срабатывает, и мы заменяем “ух” на “ло”: получается “млон”.
Теперь ни первая, ни вторая подстановки не применимы, а использование третьей дает в
результате слово “слон”. Больше ни одну подстановку сделать нельзя, и НАМ заканчивает
работу. Таким образом, приведенная система подстановок преобразует слово “муха” в слово
“слон”. При поиске образца рабочая цепочка символов просматривается сначала. Если в
строке слово-образец встречается несколько раз, то за один шаг заменяется только первое из
них. Так как на следующем шаге просмотр опять начинается с начала цепочки, после первой
выполненной замены может “сработать” совсем другая подстановка. В записи подстановок
слово-образец может быть пустым, в этом случае слово-замена приписывается в начало
рабочей строки:
→0
Такая подстановка всегда должна быть последней в списке, иначе программа
зациклится: в начало слова будут постоянно дописываться все новые и новые нули.
Если после слова-замены стоит точка, после выполнения такой подстановки работа
программы заканчивается. Например, если применить НАМ а → о. к слову “карова”, то в
результате получим “корова”, потому что после первого же действия работа программы
закончится, и последняя буква не будет заменена.
Пример. Построим НАМ для следующей задачи: удалить из строки, состоящей из
букв a и b, первый символ. Например, строка abba должна быть преобразована в bba.
Казалось бы, здесь нужно использовать систему подстановок
a→.
b→.
Однако такой НАМ будет неправильно работать для слов, начинающихся с буквы b,
например, для слова bba, в котором будет удалена последняя буква, потому что первая
подстановка выполнится раньше, чем вторая. Перестановка двух строк также не дает
решения — теперь алгоритм неправильно работает для слов, начинающихся с буквы a.
Чтобы решить эту задачу, в алфавит НАМ добавляют еще один специальный символ,
например, символ “*”. Этим символом помечают начало слова, используя подстановку
→*
Полный алгоритм выглядит так:
*a → .
*b → .
→*
Сначала срабатывает третья подстановка (ставим * в начало строки), затем, в
зависимости от первой буквы исходного слова, работает первая или вторая подстановка, и
алгоритм заканчивает работу.
Дополнительный символ похож на маркер в текстовом редакторе — он отмечает
место в тексте, с которым потом будут выполняться какие-то действия.
Как показано в теории алгоритмов, любой алгоритм для машин Тьюринга и Поста
можно записать как НАМ, и наоборот. Поэтому все три рассмотренных подхода к строгому
определению понятия «алгоритм» эквивалентны (равносильны).
Практические задания
114
1. Что делают следующие НАМ, если применить их к символьной цепочке,
состоящей из нулей и единиц:
Как будет работать каждая из программ при различных начальных состояниях ленты?
2. Напишите НАМ, который “сортирует” цифры двоичного числа так, чтобы
сначала стояли все нули, а потом — все единицы.
3. Дополните приведенный НАМ для удаления первого символа строки так,
чтобы он не зацикливался на пустом слове.
4. Напишите НАМ, который умножает двоичное число на 2, добавляя 0 в конец
записи числа.
5. Заменить последнее вхождение 0 на xx.
6. Удалить все нули и затем заменить первую группу 111 на 222.
7. Перевести число из двоичной системы в унарную (единичную).
8. Переставить символы так, чтобы в начале стояли все символы 'a', а затем все
символы 'b'.
9. Умножить двоичное число на 2, приписав к нему 0 в конце.
10. Машина выдает 1, если число, записанное в единичное системе, четное, и
стирает все символы, если число нечетное.
Контрольные вопролсы
1. Отличие НАМ от машины Тьюринга и Поста
2. Алфавит НАМ
Лабораторная №12-13
Тема: Алгоритмически неразрешимые задачи. Вычислимые и невычислимые
функции
Цель: развитие навыков по решению задач
Мы уже говорили, что любой алгоритм задает некоторую функцию, которая для
каждого входного слова, к которому применим алгоритм, задает результат — выходное
слово. Такие функции называются вычислимыми.
Вычислимая функция — это функция, для вычисления которой существует
алгоритм. Любая вычислимая функция может задаваться разными алгоритмами (разными
программами для выбранного универсального исполнителя). Например, следующие два
нормальных алгорифма Маркова заменяют во входном двоичном слове все буквы “a” на
нули и все буквы “б” на единицы:
а→0
б→1
б→1
а→0
Любая вычислимая функция может быть вычислена с помощью любого
универсального исполнителя: машин Тьюринга и Поста, нормальных алгорифмов Маркова и
др. Рассмотрим, например, такую функцию, определенную для всех натуральных чисел:
114
Попробуем составить программу для машины Тьюринга, которая вычисляет эту
функцию. Будем считать, что число записано в единичной системе счисления (в виде
цепочки единиц), и каретка в начальный момент стоит над самой левой единицей.
Четное число мы должны заменить на одну единицу, а нечетное — на пустую ленту.
Оказывается, такая программа действительно существует:
Как принято, в начальный момент машина находится в состоянии q1. Затем она
движется вправо вдоль числа, поочередно переходя из состояния q1 (пройдено четное число
единиц) в состояние q2 (пройдено нечетное число единиц) и обратно. Таким образом, если
встречен пробел и машина находится в состоянии q2, то число нечетное и нужно просто
стереть все единицы (состояние q4). Если машина закончила просмотр в состоянии q1, то
число четное; при этом нужно оставить одну единицу (состояние q3) и перейти в состояние
q4 (стереть все остальные единицы). Обратите внимание, что ячейка ( , q3) в таблице пустая
— это невозможное состояние (покажите это самостоятельно).
Таким образом, рассмотренная функция вычислима, то есть ее можно вычислять с
помощью машины Тьюринга, а значит, и с помощью любого универсального исполнителя.
Например, нормальный алгорифм Маркова для алфавита A = {1} выглядит так:
11 → ""
1→.
→ 1.
В первой подстановке две соседние единицы удаляются (слово-замена здесь пустое,
для ясности оно взято в кавычки, которыми можно ограничивать слова в НАМ). Это
происходит до тех пор, пока не будут удалены все пары, поскольку эта подстановка стоит
первой. Если остается одна единица, она удаляется с помощью второй подстановки, и работа
программы заканчивается. Если все единицы удалены (число четное), то с помощью третьей
подстановки мы ставим одну единицу и останавливаем автомат.
Существуют и невычислимые функции. Рассмотрим простой пример, предложенный
В.А. Успенским в книге “Машина Поста”. Известно, что математическая постоянная π —
иррациональное число, его десятичная запись бесконечна и не периодична. Введем функцию
h(n), которая для любого натурального числа n равна 1, если в десятичной записи числа π
есть n стоящих подряд девяток, окруженных другими цифрами, и равна нулю, если такой
цепочки девяток нет. Как вычислить значение этой функции при некотором заданном n?
Конечно, можно вычислять друг за другом десятичные знаки числа π (такие алгоритмы
математикам известны!) и проверять, не нашлась ли в полученной последовательности цифр
цепочка из n девяток. С помощью такого “наивного” алгоритма можно найти такие значения
n, при которых h(n) = 1: обнаружив требуемую цепочку, алгоритм закончит работу.
Например, анализ первых 800 знаков показывает, что h(n) = 1 при n = 0, 1, 2, 6. Но если для
какого-то n функция h(n) равна нулю, то наивный алгоритм никогда не остановится. Более
того, для этой функции вообще не существует алгоритма, который при любом n
останавливается и выдает значение h(n) в качестве результата. Поэтому такая функция
невычислима.
Практические задания
1. Докажите, что следующая функция вычислима:
В качестве доказательства напишите программу для машины Поста.
114
2. Докажите, что следующая функция вычислима:
В качестве доказательства напишите программы для машин Тьюринга и Поста, а также
НАМ.
Контрольные вопросы
1. Что такое вычислимая функция?
2. Приведите пример невычислимой функции.
3. Что такое алгоритмически неразрешимые задачи? Приведите известные вам примеры.
Лабораторная №14-15
Тема: Алгоритмы сортировки
Цель: Изучение различных методов сортировки и проведение их сравнительного
анализа.
Сортировка - это процесс упорядочения некоторого множества элементов, на
котором определены отношения порядка >, <, >=, <= (по возрастанию или убыванию).
Алгоритмы сортировки имеют большое практическое применение. Их можно встретить
почти везде, где речь идет об обработке и хранении больших объемов информации.
Некоторые задачи обработки данных решаются проще, если данные упорядочены.
Сортировка применяется во всех без исключения областях программирования, например,
базы данных или математические программы.
Оценка алгоритмов сортировки
При выборе алгоритмов сортировки необходимо поставить перед собой вопрос.
Существует ли наилучший алгоритм? Имея приблизительные характеристики входных
данных, можно подобрать метод, работающий оптимальным образом. Рассмотрим
параметры, по которым будет производиться оценка алгоритмов.
1. Число операций сортировки (сравнения и перемещения) -параметры,
характеризующие быстродействие алгоритма.
2. Объем памяти – параметр, характеризующий использование алгоритмом
дополнительной памяти.
Практически время выполнения алгоритма зависит не только от объема множества
данных (размера задачи), но и от их значений. Например, время работы некоторых
алгоритмов сортировки значительно сокращается, если первоначально данные частично
упорядочены, тогда как другие методы оказываются нечувствительными к этому свойству.
Чтобы учитывать этот факт, полностью сохраняя при этом возможность анализировать
алгоритмы независимо от данных, различают:
максимальную сложность, или сложность наиболее неблагоприятного случая, когда
метод работает дольше всего;
среднюю сложность - сложность метода в среднем (обычном) случае;
минимальную сложность - сложность в наиболее благоприятном случае, ко-гда метод
справляется быстрее всего.
Алгоритмы могут иметь разную трудоемкость (количество операций с точностью до
постоянного множителя), например, T(n2), T(n*log(n)), T(n). Минимальная сложность
всякого алгоритма сортировки не может быть меньше T(n). Максимальная сложность
метода, оперирующего сравнениями, не может быть меньше T(n*log(n)). Рассмотрим
временные сложности в порядке возрастания.
1. Сложность T(n).
114
Такая сложность получается в обычных итерационных процессах, когда на каждом
шаге метода задача размерности n сводится к задаче размерности n-1. Примером такой
сложности может служить любой цикл, в котором число итераций прямо зависит от n.
2. Сложность T(n*log(n)).
Эта сложность получается, если на каждом шаге метода выполняется не-которое
количество действий C*n, то есть зависящее от размера задачи прямо пропорционально, и
задача размерности n сводится к задаче размерностью n/m, где m – целая положительная
константа.
3. Сложность T(n2).
Такая сложность получается, когда мы имеем два вложенных цикла, число итераций,
которых зависит от n прямо пропорционально. Или другими словами, на каждом шаге
метода задача размерности n сводится к задаче размерности n-1, и при этом выполняется
некоторое количество действий C*n, то есть зависящее от n прямо пропорционально.
Примеры алгоритмов с квадратичной сложностью будут рассмотрены ниже. Это все
простые, но малоэффективные при больших n методы сортировок (в том числе получившая
широкую известность пузырьковая сортировка). Еще одним важным свойством алгоритма
является его сфера применения. Здесь основных позиций две:
внутренняя сортировка;
внешняя сортировка.
Внутренняя сортировка оперирует с массивами, помещающимися в оперативной
памяти с произвольным доступом к любой ячейке. Данные обычно сортируются на том же
месте, без дополнительных затрат. Внешняя сортировка оперирует с запоминающими
устройствами большого объема.
Проблемы оптимизации процесса сортировки различаются в обоих случаях: во
внутренней сортировке стремятся сократить число сравнений и других внутренних
операций, во внешней сортировке тоже, кроме числа сравнений, решающим фактором
является количество операций по вводу и выводу данных, т.к. доступ к данным на носителе
производится намного медленнее, чем операции с оперативной памятью.
Написать программу, в которой:
1. Задать одномерный (или двумерный, в зависимости от варианта) массив целых
чисел размерностью согласно варианту.
2. Элементы массива задать случайным образом в диапазоне 0...50.
3. Выполнить форматированный вывод исходного массива на экран.
4. Выполнить обработку массива согласно варианту. При написании программы
использовать указанный алгоритм сортировки.
5. Выполнить форматированный вывод преобразованного массива на экран.
Номер
варианта
Задание
1.
Отсортировать одномерный массив длиной N=50 по убыванию методом
простого обмена
2.
Отсортировать одномерный массив длиной N=55 по возрастанию методом
выбора
3.
Имеется одномерный массив длиной N=33. упорядочить массив методом
выбора таким образом, чтобы элементы, находящиеся на четных позициях
располагались по убыванию, а на нечетных позициях – по возрастанию.
4.
Отсортировать одномерный массив длиной N=67 методом простого обмена по
возрастанию. После упорядочивания в каждой группе повторяющихся
114
элементов оставить только один, а остальные удалить
5.
Имеется двумерный массив размерностью NхN, где N=10. Отсортировать все
столбцы методом простого обмена так, чтобы элементы в них располагались по
возрастанию
6.
Имеется одномерный массив длиной N=45. отсортировать по убыванию
методом выбора те элементы массива, которые являются четными числами.
7.
Имеется одномерный массив длиной N=38. упорядочить массив методом
простого обмена таким образом, чтобы элементы, находящиеся на четных
позициях располагались по возрастанию, а на нечетных позициях – по
убыванию.
8.
Имеется одномерный массив длиной N=70. отсортировать по возрастанию с
помощью метода выбора те элементы массива, которые располагаются на
нечетных позициях.
9.
Имеется двумерный массив размерностью NхN, где N=9. Отсортировать все
строки методом простого обмена так, чтобы элементы в них располагались по
убыванию
10.
Имеется двумерный массив размерностью NхN, где N=8. отсортировать все
строки методом выбора так, чтобы элементы в них располагались по
возрастанию.
11.
Имеется двумерный массив размерностью NхN, где N=10. Отсортировать все
строки методом выбора так, чтобы элементы в них располагались по убыванию
12.
Отсортировать одномерный массив длиной N=29 по убыванию методом выбора
13.
Отсортировать одномерный массив длиной N=31 по возрастанию методом
простого обмена
14.
Имеется двумерный массив размерностью NхN, где N=9. отсортировать все
столбцы методом выбора так, чтобы элементы в них располагались по
возрастанию.
15.
Отсортировать по убыванию одномерный массив длиной N=44 методом выбора.
После упорядочивания в каждой группе повторяющихся элементов оставить
только один, а остальные удалить
Контрольные вопросы
1. Что такое сортировка?
2. Перечислите основные методы сортировки.
3. Приведите примеры практического использования сортировки.
4. По каким параметрам можно оценить алгоритмы сортировки?
5. Что такое трудоемкость алгоритма?
6. Чем отличаются внешняя и внутренняя сортировка?
7. Проведите сравнительный анализ эффективности алгоритмов сортировки.
8. Что объединяет методы сортировки «пузырьком», вставками и выбором?
114
9. В каком методе сортировки необходима дополнительная память?
4.
САМОСТОЯТЕЛЬНАЯ РАБОТА СТУДЕНТА
СРСП №1
Тема: Примеры интерпретации простейших операций одной формализации в другую.
Цель: знать определения формальной теории и интерпретации формальной теории
Формальная теория T – это:
1. множество A символов, образующих алфавит A и множество слов A*;
2. множество F слов в алфавите A, F Ì A*, которые называются формулами;
3. подмножество B формул, B Ì F, которые называются аксиомами;
4. множество R отношений на множестве формул, которые называются правилами
вывода.
Множество символов A, как правило, конечно. Обычно, для образования символов
используют буквы, к которым приписывают в качестве индексов натуральные числа.
Множество формул F обычно задается индуктивным определением, например, с помощью
формальной грамматики. Как правило, это множество бесконечно. Множества A и F в
совокупности определяют язык или сигнатуру формальной теории. Множество аксиом B
может быть конечным или бесконечным. Если множество аксиом бесконечно, то оно
задается с помощью конечного множества схем аксиом и правил порождения. Множество
правил вывода R, как правило, конечно.
Интерпретация формальной теории
Интерпретацией формальной теории T в область интерпретации называется функция
I, которая каждой формуле формальной теории однозначно сопоставляет некоторое
содержательное высказывание относительно объектов множества. Это высказывание может
быть истинным или ложным. Если высказывание является истинным, то говорят, что
формула выполняется в данной интерпретации. Интерпретация I называется моделью
множества формул, если все формулы этого множества выполняются в интерпретации I.
Интерпретация I называется моделью формальной теории T , если все формулы этой теории
выполняются в интерпретации I (то есть все выводимые формулы оказываются истинными в
данной интерпретации).
Общезначимость и непротиворечивость
Формула называется общезначимой (или тавтологией), если она истинна в любой
интерпретации. Формула называется противоречивой, если она ложна в любой
интерпретации. Формула G называется логическим следствием множества формул, если G
выполняется в любой модели. Формальная теория T называется семантически
непротиворечивой, если ни одна ее теорема не является противоречием.
Таким образом, формальная теория пригодна для описания тех множеств, которые
являются ее моделями.
Модель для формальной теории T существует тогда и только тогда, когда T
семантически непротиворечива. Формальная теория T называется формально
непротиворечивой, если в ней не являются выводимыми одновременно формулы F‫ך‬F. Теория
T формально непротиворечива тогда и только тогда, когда она семантически
непротиворечива.
СРСП №2
Тема: Сводимости множеств.
Цель: знать определения сводящей функции
114
Говорят, что множество A натуральных чисел m - сводится к другому множеству B
натуральных чисел, если существует всюду определенная вычислимая функция f : N -> N с
таким свойством:
для всех
. Такая функция называется m -сводящей A к B. Обозначение: A <=m
B.
Теорема 31.(а) Если A <=m B и B разрешимо, то A разрешимо.(б) Если A <=m B и B
перечислимо, то A перечислимо. (в) A <=m A ; если A <=m B и B <=m C, то A <=m C. (г) Если
A <=m B, то N \ A <=m N \ B.
Все эти свойства почти очевидны. Пусть A <=m B и мы имеем разрешающий алгоритм
для B. Чтобы узнать, принадлежит ли данное x множеству A, мы вычисляем f(x) и узнаем,
принадлежит ли f(x) множеству B. Другими словами, a(x)=b(f(x)), если a характеристическая
функция множества A, а b характеристическая функция множества B ; поэтому если b
вычислима, то и a вычислима как композиция вычислимых функций.
Такое же равенство можно записать для " полухарактеристических " функций,
поэтому из перечислимости B следует перечислимость A. Можно сказать и иначе:
множество A является прообразом перечислимого множества B при вычислимом
отображении f, и потому перечислимо.
Тождественная функция, очевидно, m -сводит A к A. Если функция f сводит A к B, а
функция g сводит B к C, то
так что композиция функций g и f сводит A к C.
Наконец, функция, сводящая A к B, будет сводить и N \ A к N \ B.
Буква " m " в названии исторически происходит из термина "many-one-reducibility";
впрочем, как отмечает M.Сипсер в своем учебнике по теории сложности вычислений, вместо
этого лучше говорить " mapping reducibility " (сводимость с помощью отображений),
сохраняя букву m в обозначении.
Отметим, что это определение не симметрично относительно перехода к дополнению,
если это делается только в одном из множеств: вовсе не обязательно A <=m N \ A, хотя всегда
A <=m A.
m-полные множества
Теорема. Среди перечислимых множеств существуют наибольшие с точки зрения m сводимости, то есть множества, к которым m -сводится любое перечислимое множество.
Таковым является универсальное множество (формально надо перейти от пар к их
номерам). Пусть
перечислимое множество пар натуральных чисел,
универсальное для класса перечислимых множеств натуральных чисел. Рассмотрим
множество V номеров всех пар, входящих в U (для какой-то вычислимой нумерации пар
). Другими словами,
Пусть T произвольное перечислимое множество. Тогда T=Un при некотором n и
потому
Таким образом, функция
сводит T к V.
Наибольшие относительно m -сводимости перечислимые множества называют m полными (точнее, m - полными в классе перечислимых множеств ).
Заметим, что если K <=m A для перечислимых множеств K и A и при этом K является
m -полным, то и A является m -полным (в силу транзитивности).
Если универсальное множество является главным, то его диагональ также m -полна:
114
Теорема. Пусть
перечислимых
множеств.
главное универсальное множество
Тогда
его
"
диагональное
для класса
сечение"
является m -полным.
(В частности, множество всех самоприменимых программ является m -полным.)
Очевидно, D перечислимо. Пусть K произвольное перечислимое множество.
Рассмотрим перечислимое множество пар V = K x N. Его сечения Vn будут либо пусты (при
), либо совпадать со всем N (при
).
Поскольку множество U является главным, существует всюду определенная функция
s, для которой Vn=Us(n). Другими словами, Us(n) совпадает с N при
и пусто при
. Следовательно,
потому
) при
(и потому
) при
и
(и
. Таким образом, s сводит K к D.
СРСП №3
Тема: Креативные и продуктивные множества.
Цель: знать определения
Говорят, что множество A является продуктивным, если существует вычислимая (не
обязательно всюду определенная) функция f с таким свойством: она применима к любому
номеру n любого подмножества Wn множества A и дает элемент в их разности:
Докажите, что продуктивное множество не может быть иммунным.
Ясно, что требования в определении продуктивности лишь часть требований из
определения эффективно неперечислимого множества, так что любое эффективно
неперечислимое множество продуктивно. Удивительным образом оказывается, что верно и
обратное.
Теорема. Пусть A продуктивное множество, K произвольное перечислимое
множество. Тогда дополнение к K m -сводится к A.
(Из этого следует, что A является эффективно неперечислимым, см. выше.)
Пусть f функция, которая существует по определению продуктивности (и дает
элемент вне подмножества с указанным номером).
Мы построим всюду определенную вычислимую функцию s с такими свойствами:


.
(второе свойство подразумевает, что f(s(x)) определено при
). Прежде чем
делать это с помощью теоремы о неподвижной точке, заметим, что в первом случае f(s(x))
определено и принадлежит A: поскольку множество с номером s(x) пусто и является
подмножеством A, число f(s(x)) должно быть элементом A. Напротив, во втором случае
f(s(x)) не принадлежит A. В самом деле, если бы это было не так, то множество W s(x) было бы
подмножеством A, и потому число f(s(x)) должно было бы быть элементом A, не входящим в
это подмножество а оно входит.
Поэтому если нам удастся построить такую функцию s, то функция x -> f(s(x)) будет
m -сводить дополнение множества K к множеству A, как мы и обещали. Как же ее строить?
Если бы во втором свойстве (для
) стояло не f(s(x)), а, скажем, просто f(x),
никакой проблемы бы не было. Как обычно, мы рассмотрели бы перечислимое множество
пар
сечения этого множества имели бы требуемый вид и осталось бы только
воспользоваться тем, что нумерация главная. Но в нашем случае, когда в правой части
114
второго свойства стоит f(s(x)), так просто поступить нельзя: как в истории о курице и яйце,
для построения V нам надо иметь s(x), а для построения s(x) надо иметь V.
Именно такого рода трудности позволяет преодолевать теорема о неподвижной точке.
Построим всюду определенную вычислимую функцию двух аргументов h с такими
свойствами:


.
(Подобные вещи мы делали многократно последний раз в предыдущем абзаце.
Отметим, что f(t) может быть и не определено, тогда под {f(t)} мы понимаем пустое
множество.) По теореме о неподвижной точке (для перечислимых множеств) при каждом x
функция
имеет неподвижную точку, и, как мы говорили в разделе о
неподвижной точке с параметром, эту неподвижную точку можно выбрать вычислимо
зависящей от x. Таким образом, существует всюду определенная вычислимая функция s, для
которой
Ws(x)=Wh(x,s(x))
при всех x. Это равенство можно продолжить:
- это ровно то, чего мы и хотели. Заметим, что значение f(s(x)) определено при всех x
(иначе
, и f(s(x)) должно быть определено). Тем самым, теорема о неподвижной
точке позволяет отыскать взаимно согласованные яйцо и курицу и завершает доказательство.
Перечислимые множества, дополнения которых продуктивны, называются
креативными (creative; иногда это слово переводят как " творческие "). Название объясняется
так: это множество (точнее, его дополнение) более изобретательно, чем любой
алгоритмический процесс: если кто-то предлагает способ порождать некоторые элементы из
дополнения, то в ответ можно указать элемент дополнения, который нельзя получить таким
способом.
Как мы видим, творческие множества, перечислимые множества с эффективно
неперечислимым дополнением и m -полные множества один и тот же класс, и любые два
множества из этого класса в некотором смысле изоморфны (отличаются лишь вычислимой
перестановкой).
Если множество продуктивно, то можно порождать его элементы следующим
индуктивным процессом. На первом шаге имеется пустое множество. Применив к нему
продуктивную функцию (е функцию, существующую по определению продуктивного
множества), мы получим некоторый элемент. Он образует одноэлементное подмножество.
Применив к этому подмножеству продуктивную функцию, получим другой элемент. К
полученному двухэлементному подмножеству можно снова применить продуктивную
функцию и так далее. Получится бесконечная вычислимая последовательность элементов
продуктивного множества. (Это мы уже делали, когда доказывали, что эффективно
неперечислимое множество содержит бесконечное перечислимое подмножество.) Но этот
индуктивный процесс можно " трансфинитно " продолжить, по крайней мере еще немного:
имея перечислимое подмножество нашего продуктивного множества (множество членов
последовательности), можно найти еще один элемент продуктивного множества (так сказать,
элемент номер
). Добавим его к последовательности, снова применим продуктивную
функцию,
получится
последовательность,
114
-ый
элемент
-й элемент,
и
так
-й,...,
далее,
затем
-й элемент и т.д.
получится
новая
СРСП №4
Тема: Простые и максимальные множества.
Цель: знать определения
Существуют и другие конструкции перечислимых неразрешимых множеств.
Вот одна из них (предложенная Э.Постом).
Назовем множество иммунным, если оно бесконечно, но не содержит
бесконечных перечислимых подмножеств. Перечислимое множество называют
простым, если его дополнение иммунно. (Очевидно, такое множество не может
быть разрешимым.)
Теорема.Существует простое множество.
Нам нужно, чтобы перечислимое множество S имело иммунное дополнение.
Это означает, что S должно пересекаться с любым бесконечным перечислимым
множеством. Чтобы гарантировать это, полезно для каждого перечислимого
множества V добавить какой-то его элемент в S (хотя бы для бесконечных V ).
При этом надо позаботиться о том, чтобы вне S осталось бесконечно много
элементов. Это можно гарантировать, если добавлять достаточно большие
элементы (например, из множества номер i добавлять только один элемент,
притом больший 2i ).
Объясним конструкцию подробнее. Пусть W универсальное перечислимое
множество пар, среди сечений Wi которого встречаются все перечислимые
множества натуральных чисел. Будем называть Wi " перечислимым множеством
номер i " (при этом разным номерам может соответствовать одно и то же
множество). Рассмотрим множество пар
множество перечислимо (как пересечение
W
и
разрешимого
. Это
множества
). Перечисляя его, будем отбрасывать пары, у которых первый
член уже встречался ранее. Останется некоторое перечислимое подмножество
. Рассмотрим теперь перечислимое множество S вторых членов пар,
входящих в T'.
Это множество пересекается с любым бесконечным перечислимым
множеством. В самом деле, если Wi бесконечно, то оно содержит и числа, большие
2i, поэтому в T (а, значит, и в T' ) есть пары с первым членом i. Второй член такой
пары из T' будет лежать и в S, и в Wi.
С другой стороны, множество S имеет бесконечное дополнение, поскольку
среди чисел от 0 до 2n - 1 максимум n различных чисел могут принадлежать S
(это числа, попавшие в S c одной из первых n вертикалей все остальные будут
уже больше 2n ).
СРСП №5
Тема: Алгоритмы на графах.
Цель: уметь использовать алгоритмы при решении задач
Граф - совокупность точек и линий, в которой каждая линия соединяет две точки.
Точки называются вершинами, или узлами, графа, линии - ребрами графа. Если ребро
соединят две вершины, то говорят, что оно им инцидентно; вершины, соединенные ребром
называются смежными. Две вершины, соединенные ребром, могут совпадать; такое ребро
называется петлей. Число ребер, инцидентных вершине, называется степенью вершины.
Если два ребра инцидентны одной и той же паре вершин, они называются кратными; граф,
содержащий кратные ребра, называется мультиграфом.
Ребро, соединяющее две вершины, может иметь направление от одной вершины к
другой; в этом случае оно называется направленным, или ориентированным, и изображается
стрелкой. Граф, в котором все ребра ориентированные, называется ориентированным графом
114
(орграфом); ребра орграфа часто называют дугами. Дуги именуются кратными, если они не
только имеют общие вершины, но и совпадают по направлению. Иногда нужно
рассматривать не весь граф, а его часть (часть вершин и часть ребер). Часть вершин и все
инцидентные им ребра называются подграфом; все вершины и часть инцидентных им ребер
называются суграфом. Циклом называется замкнутая цепь вершин. Деревом называется граф
без циклов. Остовным деревом называется связанный суграф графа, не имеющий циклов.
Граф однозначно задан, если заданы множество его вершин, множество ребер и
указаны все инцидентности (т.е. указано, какие вершины какими ребрами соединены).
Наиболее наглядно граф задается рисунком; однако не все детали рисунка одинаково важны;
в частности, несущественны геометрические свойства ребер (длинна, кривизна и т.д.) и
взаимное расположение вершин на плоскости.
Для неориентированного ребра порядок, в котором указанны соединяемые им
вершины, не важен. Для ориентированного ребра важно: первой указывается вершина, из
которой выходит ребро.
Маршрут, или путь - это последовательность ребер в неориентированном графе, в
котором конец каждого ребра совпадает с началом следующего ребра. Число ребер маршрута
называется его длинной.
Графы широко используются как в самой математике, так и в ее приложениях. Они
применяются при построении различных математических моделей: линий электропередачи,
сетей автодорог, линий воздушных сообщений и пр.
Задача состоит в том, найти путь из вершины A в вершину B. Будем задавать граф
матрицей смежности, т.е. квадратной таблицей NxN, в которой на пересечении i-й строки и jго столбца значение TRUE, если i и j соединены ребром, и FALSE в противном случае.
Поиск в ширину.
Подобно тому как, согласно принципу Гюйгенса, каждая точка волнового фронта
является источником вторичной волны, мы, отправляясь из заданной вершины A, посещаем
все смежные с ней вершины (т.е. вершины, в которые ведут стрелки из A). Каждая
посещенная вершина становится источником новой волны и т.д. При этом необходимо
позаботиться о том, чтобы не вернутся в ту вершину, в которой уже были.
Для
реализации
алгоритма
понадобятся:
матрица m[1..n, 1..n] - матрица смежности графа;
вспомогательный массив queue[1..n], в котором будет формироваться очередь, т.е. тип
данных первый вошел – первый вышел (FIFO). Размер его достаточен, так как мы не
посещаем вершины дважды. С массивом queue связаны две переменные - head и tail. В
переменной head будет находиться номер текущей вершины, из которой идет волна, а при
помощи переменной tail новые вершины помещаются в "хвост" очереди queue;
вспомогательный массив visited[1..n], который нужен для того, чтобы отмечать уже
пройденные вершины (visited[i]=TRUE <=> вершина i пройдена);
вспомогательный массив prev[1..n] для хранения пройденных вершин. В этом массиве и
будет сформирован искомый путь;
переменная f, которая примет значение TRUE, когда путь будет найден.
Кроме того, мы введем несколько вспомогательных переменных, которые
понадобятся при организации циклов.
Program breadth_first_search;
Const n=9;
m:array[1..n, 1..n] of boolean =
(
(False, True, True, False, False, False, False, False, False),
(True, False, True, False, False, False, True, True, False),
(True, True, False, True, True, False, False, False, False),
(False, False, True, False, True, False, False, False, False),
(False, False, True, True, False, True, False, True, False),
114
(False, False, False, False, True, False, True, True, True ),
(False, True, False, False, False, True, False, True, True ),
(False, True, False, False, True, True, True, False, False),
(False, False, False, False, False, True, True, False, False)
);
Var A, B: integer;
Procedure A_to_B(A, B: integer);
Var
Visited: array[1..n] of boolean;
Prev: array[1..n] of integer;
c: array[1..n] of integer;
head, tail: integer;
f: boolean;
i, v, k: integer;
Begin
head:=1;
tail:=1;
f:=False;
For i:=1 to n do
Begin
Visited[i]:=False;
Prev[i]:=0
End;
C[tail]:=A;
Visited[A]:=True;
While (head<=tail) and not f do
Begin
v:=C[head];
head:=head+1;
For k:=1 to n do
if m[v, k] and not Visited[k] then
Begin
tail:=tail+1;
C[tail]:=k;
Visited[k]:=True;
Prev[k]:=v;
if k=B then
Begin
f:=true;
break
End
End
End;
if f then
Begin
k:=B;
Write(B);
While Prev[k]<>0 do
Begin
Write('<-', Prev[k]);
k:=Prev[k]
end
114
End
else
Write('Пути из ', A, ' в ', B, ' нет')
end;
Begin
Write('A= '); readln(A);
Write('B= '); readln(B);
A_to_B(A, B)
End.
Поиск в глубину
Идея поиска в глубину проста: отправляясь от текущей вершины, мы находим новую
(еще не пройденную) смежную с ней вершину, которую помечаем как пройденную и
объявляем текущей. После этого процесс возобновляется. Если новой смежной вершины нет
(тупик), возвращаемся к той вершине, из которой попали в текущую, и делаем следующую
попытку. Если попадем в вершину B, печатаем путь. Если все вершины исчерпаны - такого
пути нет.
Заметим, что построенный таким образом алгоритм способен находить все пути из A
в B, но первый найденный необязательно должен быть кратчайшим.
Как обычно, алгоритм с возвратами легче всего оформить с помощью рекурсивной
процедуры.
Рассмотреть другие алгоритмы
СРСП №6
Тема: Жадные приближенные алгоритмы.
Цель: уметь применять жадный алгоритм
Жадный Алгоритм (greedy algorithm) — это алгоритм, который на каждом шагу делает
локально наилучший выбор в надежде, что итоговое решение будет оптимальным.
К примеру, алгоритм Дейкстры нахождения кратчайшего пути в графе вполне себе жадный,
потому что мы на каждом шагу ищем вершину с наименьшим весом, в которой мы еще не
бывали, после чего обновляем значения других вершин. При этом можно доказать, что
кратчайшие пути, найденные в вершинах, являются оптимальными.
К слову, алгоритм Флойда, который тоже ищет кратчайшие пути в графе (правда,
между всеми вершинами), не является примером жадного алгоритма. Флойд демонстрирует
другой метод — метод динамического программирования.
Использование жадного алгоритма довольно стандартное. Рассмотрим его на примере
следующей задачи:
Задача о расписании
Пусть программисту-фрилансеру Васе Пупкину дано n заданий. У каждого задания
известен свой дедлайн, а также его стоимость(то есть если он не выполняет это задание, то
он теряет столько-то денег). Вася настолько крут, что за один день может сделать одно
задание. Выполнение задания можно начать с момента 0. Нужно максимизировать прибыль.
Классический пример применения жадины: Васе выгодно делать самые «дорогие
задания», а наименее дорогие можно и не выполнять — тогда прибыль будет максимальна.
Возникает вопрос: каким образом распределить задания? Будем перебирать задания в
порядке убывания стоимости и заполнять расписание следующим образом: если для заказа
есть еще хотя бы одно свободное место в расписании раньше его дедлайна, то поставим его
на самое последнее из таких мест, в противном случае в срок мы его не можем выполнить,
значит поставим в конец из свободных мест.
114
Методические рекомендации по СРС
СРС №1
Тема: Формализация понятия алгоритма
Цель: знать подходы к формализации алгоритма
Понятие алгоритма, которое мы ввели можно назвать понятием алгоритма в
интуитивном смысле. Оно имеет нечеткий, неформальный характер, ссылается на
некоторые точно не определенные, но интуитивно понятные вещи. Например, при
определении и обсуждении свойств алгоритма мы исходили из возможностей
некоторого исполнителя алгоритма. Его наличие предполагалось, но ничего
определенного о нем не было известно. Говоря языком математики, ни
аксиоматического,
ни
исчерпывающего
конструктивного
определения
исполнителя мы так и не дали.
Как фундаментальное
научное
понятие
алгоритм требует
более
обстоятельного изучения. Оно невозможно без уточнения понятия «алгоритм»,
более строгого его описания или, как еще говорят, без его формализации.
Известно несколько подходов к формализации понятия «алгоритм»:
• теория конечных и бесконечных автоматов;
• теория вычислимых (рекурсивных) функций;
• λ-исчисление Черча.
Все эти возникшие исторически независимо друг от друга подходы
оказались впоследствии эквивалентными.
Главная цель формализации понятия алгоритма такова: подойти к решению
проблемы алгоритмической разрешимости различных математических задач, т.е.
ответить на вопрос, может ли быть построен алгоритм, приводящий к решению
задачи. Мы рассмотрим постановку этой проблемы и некоторые результаты
теории алгоритмической разрешимости задач, но вначале обсудим формализацию
понятия алгоритма в теории автоматов на примере машин Поста, Тьюринга, а
также нормальных алгоритмов Маркова, а затем — основы теории рекурсивных
функций. Идеи λ-исчислений Черча реализованы в языке программирования
Лисп.
СРС №2
Тема: Свойства машины Тьюринга как алгоритма
Цель: знать свойства машины Тьюринга
На примере машины Тьюринга хорошо прослеживаются свойства
алгоритмов. Попросите учащихся показать, что машина Тьюринга обладает всеми
свойствами алгоритма.
Дискретность. Машина Тьюринга может перейти к (к + 1) - му шагу только
после выполнения каждого шага, т.к именно каждый шаг определяет, каким будет
(к + 1) - й шаг.
Понятность. На каждом шаге в ячейку пишется символ из алфавита, автомат
делает одно движение (Л, П, Н), и машина Тьюринга переходит в одно из
описанных состояний.
Детерминированность. В каждой клетке таблицы машины Тьюринга записан
лишь один вариант действия. На каждом шаге результат определен однозначно,
следовательно,
последовательность
шагов
решения
задачи
определена
однозначно, т.е. если машине Тьюринга на вход подают одно и то же входное
слово,114то выходное слово каждый раз будет одним и тем же.
Результативность. Содержательно результаты каждого шага и всей
последовательности шагов определены однозначно, следовательно, правильно
написанная машина Тьюринга за конечное число шагов перейдет в состояние q0,
т.е. за конечное число шагов будет получен ответ на вопрос задачи.
Массовость. Каждая машина Тьюринга определена над всеми допустимыми
словами из алфавита, в этом и состоит свойство массовости. Каждая машина
Тьюринга предназначена для решения одного класса задач, т.е. для каждой
задачи пишется своя (новая) машина Тьюринга.
СРС №3
Тема: Понятие о метаязыке и метатеории
Цель: знать основные понятия и определения
Метатеория (от греч. μετά – после и теория; букв. теория о некоторой
другой теории) – одно из важнейших понятий современной логики, математики,
философии и методологии науки; теория, анализирующая структуру, методы и
свойства некоторой другой теории – предметной, или объектной, теории. В самом
общем смысле метатеорией является любой метаязык, описывающий структуру,
свойства и т.п. какого-либо языка-объекта. Согласно выработанным в 20 в.
представлениям (У. Сепир, Б.Уорф, К.Поппер и др.), каждый язык является
концептуализацией мира или его фрагментов, т.е. теорией (возможно, не очень
богатой, как, напр., язык знаков светофора, или очень богатой в случае
естественного языка). Поэтому соответствующий метаязык выступает в качестве
метатеории по отношению к теории, сформулированной в языке-объекте.
Исторически термин «метатеория» был первоначально введен в начале 20 в. в
исследованиях по основаниям математики и логики (Д.Гильберт, К.Гёдель,
А.Тарский, Р.Карнап, А.Чёрч, С.Клини и др.) применительно к изучению
математических и логических теорий, результатом чего явились программы
построения метаматематики и металогики. Именно в этой области в
метатеоретических исследованиях были получены важные результаты.
Основная задача построения метатеории состоит в уточнении (экспликации)
соответствующих предметных теорий и анализе их свойств. При этом в рамках
общей программы проведения метатеоретических исследований на предметные
теории и метатеории не накладывается никаких ограничений: они могут быть
содержательными, дедуктивными, частично или полностью формализованными и
могут
использовать
любые
логические
средства.
Результатами
таких
исследований явились попытки построения метабиологии, метахимии, метатеории
физического знания, метатеории теорий систем и далее метанауки, однако в них
пока не получены значительные метатеоретические достижения, сравнимые с
теми, которые имеются в метаматематике и металогике.
Метатеория, которая строится по отношению к т.о. представленной
предметной теории, является содержательной теорией, т.е. она состоит из
содержательно
понимаемых
элементов
естественного
языка.
В
ней
формулируются метатеоремы – теоремы о теоремах, которые описывают
синтаксические и семантические свойства соответствующей предметной
(формализованной) теории.
Для того, чтобы метаматематика выполнила свою основную функцию –
обоснования содержательной математики, она, согласно Гильберту, должна
пользоваться только т.н. финитными методами, то есть использовать лишь
конечные конструкции и конструктивные доказательства, не допускающие
применения абстракции актуальной бесконечности, которая играет важную роль в
содержательной математике и в ее формализованном представлении. В рамках
этой программы был получен ряд важных метатеоретических результатов. Так,
была 114
доказана синтаксическая метатеорема о дедукции, которая устанавливает
связь между понятием выводимости (доказуемости) в данной предметной теории
(напр., в исчислении высказываний или исчислении предикатов) и логической
операцией импликации, входящей в алфавит данной предметной теории.
Примером семантической метатеоремы является теорема о полноте классического
исчисления высказываний, согласно которой для этого исчисления понятия
доказуемой формулы (формальной теоремы) и формулы, истинной при некоторой
его интерпретации, совпадают. Некоторые понятия метаматематики носят
смешанный – синтаксически-семантический характер. Таково, напр., понятие
непротиворечивости, которое синтаксически определяется как невыводимость в
предметной теории противоречия, т.е. конъюнкции некоторой формулы и ее
отрицания, а в семантическом плане означает соответствие данной предметной
теории некоторой ее интерпретации. Эквиваленность этих определений является
нетривиальным метатеоретическим фактом.
Вслед за результатами Гёделя были вскрыты и другие ограниченности
формализмов: Чёрч доказал неразрешимость проблемы разрешения для узкого
исчисления предикатов, Тарский показал невыразимость предиката истинности
для какого-либо исчисления средствами этого же исчисления и т.д. В связи с этим
потребовалась определенная модификация программы Гильберта – необходимо
было найти новые, более сильные, чем финитные, но также достаточно
убедительные методы метатеоретических рассуждений. Значительный прогресс в
этом отношении был получен в середине и во 2-й пол. 20 в. Г.Генценом,
В.Аккерманом, П.С.Новиковым, К.Шютте, А.С.Есениным-Вольпиным и др.;
метаматематические и металогические исследования остаются актуальной
задачей и в настоящее время.
СРС №4
Тема: Алгоритмы как формальные системы
Цель: знать основные понятия и определения
Во всех сферах своей деятельности, и частности в сфере обработки информации,
человек сталкивается с различными способами или методиками решения задач. Они
определяют порядок выполнения действий для получения желаемого результата – мы можем
трактовать это как первоначальное или интуитивное определение алгоритма. Некоторые
дополнительные требования приводят к неформальному определению алгоритма:
Определение 1.1 Алгоритм - это заданное на некотором языке конечное предписание,
задающее конечную последовательность выполнимых элементарных операций для решения
задачи, общее для класса возможных исходных данных.
Пусть D – область (множество) исходных данных задачи, а R – множест-во
возможных результатов, тогда мы можем говорить, что алгоритм осуществ-ляет
отображение D --> R. Поскольку такое отображение может быть не полным, то вводятся
следующие понятия:
Алгоритм называется частичным алгоритмом, если мы получаем результат только для
некоторых d є D и полным алгоритмом, если алгоритм получает правильный результат для
всех d є D.
Несмотря на усилия исследователей отсутствует одно исчерпывающе строгое
определение понятия алгоритм, в теории алгоритмов были введены различные формальные
определения алгоритма и удивительным научным результатом является доказательство
эквивалентности этих формальных определений в смысле их равномощности.
Варианты словесного определения алгоритма принадлежат российским ученым А.Н.
Колмогорову и А.А. Маркову
Определение 1.2 (Колмогоров): Алгоритм – это всякая система вычис-лений,
выполняемых по строго определенным правилам, которая после какого-либо числа шагов
заведомо приводит к решению поставленной задачи.
114
Определение 1.3 (Марков): Алгоритм – это точное предписание, определяющее
вычислительный процесс, идущий от варьируемых исходных данных к искомому результату.
Отметим, что различные определения алгоритма, в явной или неявной форме,
постулируют следующий ряд требований:

алгоритм должен содержать конечное количество элементарно выполнимых
предписаний, т.е. удовлетворять требованию конечности записи;

алгоритм должен выполнять конечное количество шагов при решении задачи,
т.е. удовлетворять требованию конечности действий;

алгоритм должен быть единым для всех допустимых исходных данных, т.е.
удовлетворять требованию универсальности;

алгоритм должен приводить к правильному по отношению к поставленной
задаче решению, т.е. удовлетворять требованию правильности.
Другие формальные определения понятия алгоритма связаны с введением
специальных математических конструкций (машина Поста, машина Тьюринга, рекурсивновычислимые функции Черча) и постулированием тезиса об эквивалентности такого
формализма и понятия «алгоритм».
114
Download