Опубликован: 21.08.2007 | Уровень: специалист | Доступ: свободно | ВУЗ: Тверской государственный университет
Лекция 7:

Алгоритмы: структурированные программы

< Лекция 6 || Лекция 7: 12 || Лекция 8 >
Аннотация: Алгоритмы и модели вычислений. Структурированные программы: синтаксис и семантика. Арифметические функции, вычислимые структурированными программами

Что такое алгоритм?

Первоначальной целью теории алгоритмов является классификация всех задач на алгоритмически разрешимые и неразрешимые, т.е. на те, для которых существуют решающие их алгоритмы, и те, для которых таких алгоритмов нет. Неформально под алгоритмом \mathcal{A} можно понимать выраженный в некотором языке набор правил (предписание, рецепт, способ), позволяющий применить к исходным (входным) данным x из некоторого множества допустимых данных X последовательность дискретных действий (операций, команд), приводящую к определенному результату - выходным данным y= \mathcal{A(x) из некоторого множества Y. В этом случае говорят, что алгоритм \mathcal{A} вычисляет функцию F(x)= \mathcal{A}(x) типа X -> Y. Это нестрогое определение вполне подходит в тех случаях, когда для некоторой функции нам предъявляется "объект", называемый алгоритмом ее вычисления (например, алгоритм Эвклида для вычисления наибольшего общего делителя двух целых чисел), и можно легко проверить, позволяет ли он действительно вычислить требуемую функцию. Однако оно совершенно не годится для доказательства того, что для заданной функции никакого алгоритма нет.

Начиная с тридцатых годов ХХ века, был предпринят ряд исследований для формализации понятия алгоритма. Перечислим некоторые из предложенных разными авторами в разное время формальных моделей: машины Тьюринга-Поста, частично-рекурсивные функции (Гедель, Клини), \lambda -исчисление (Черч, Клини), итеративные автоматы Неймана, нормальные алгорифмы Маркова, счетчиковые автоматы Минского, автоматы на графах Колмогорова-Барздиня и др. Заложенные в них идеи в значительной степени повлияли затем на архитектуру и языки программирования реальных компьютеров (например, на базе \lambda -исчисления построен широко применяемый в задачах искусственного интеллекта язык ЛИСП, а из нормальных алгорифмов Маркова произошел хорошо подходящий для текстовой обработки язык РЕФАЛ). Каждый из многочисленных языков программирования также задает некоторую формальную модель алгоритмов. Мы вначале рассмотрим один из простейших таких языков - простые структурированные программы. А затем сравним их с двумя другими моделями алгоритмов: описаниями частично рекурсивных функций и машинами Тьюринга.

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

Напомним, что через N обозначается множество натуральных чисел, т.е. N={0,1,2,...}. Для частичной n - местной арифметической функции f: Nn -> N через \Delta _{f} обозначим область ее определения. Чтобы указать, что f не определена на некотором наборе чисел a1,..., an будем писать f(a_{1},\dots , a_{n})=\infty, а если f на этом наборе определена, то будем писать f(a_{1},\dots , a_{n}) < \infty. Таким образом, \delta _{f} =\{  (a_{1},\dots , a_{n})  |  f(a_{1},\dots , a_{n}) < \infty  \}.

Структурированные программы

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

Определим вначале синтаксис структурированных программ. Зафиксируем для этого некоторое счетное множество имен переменных Var, которые будут использоваться в программах. Как обычно, будем считать, что оно включает имена x, x1,x2,..., y, y1,..., z,z1,... и т.п. В последующих определениях x, y, z - это произвольные переменные из Var.

Определение 7.1. Оператор присваивания. Присваивание - это выражение одного из следующих трех видов:

  • x := x+1
  • x := 0
  • x := y.

Определение 7.2. Условия. Условие - это выражение одного из двух видов:

а) x = y или б) x < y.

Структурированные программы определяются индуктивно.

Определение 7.3. Структурированные программы.

  • Каждое присваивание - это структурированная программа.
  • Если \Pi _{1} и \Pi _{2} - структурированные программы, то и \Pi = \Pi _{1} ; \Pi _{2} - это структурированная программа.
  • Если \Pi _{1} и \Pi _{2} - структурированные программы, а \Phi - это условие, то

    \Pi= \mbox{ если } \Phi \mbox{ то } \Pi_1  \mbox{ иначе } \Pi_2  \mbox{ конец }

    является структурированной программой.

  • Если \Pi _{1} - структурированная программа, а \Phi - это условие, то

    \Pi=  \mbox{ пока } \Phi \mbox{  делай }\Pi_1

    все является структурированной программой.

  • Других структурированных программ нет.

Конструкция в п. (б) называется последовательным применением или композицией программ \Pi _{1} и \Pi _{2}, конструкция в п. (в) называется условным оператором ; конструкция в п. (г) - это оператор цикла, \Phi - условие цикла, а \Pi _{1} - тело цикла.

С помощью структурированных программ (далее называемых просто программами) вычисляются (частичные) функции от натуральных аргументов, принимающие натуральные значения. С каждой программой \Pi свяжем естественным образом множество входящих в нее переменных Var_{\Pi } (определите это множество индукцией по построению программы). В процессе работы программа изменяет значения этих переменных. Операционная семантика задает правила такого изменения.

Определение 7.4. Состояние - это отображение \sigma из множества переменных Var во множество N. Для x \in  Var через \sigma (x) обозначим значение переменной x в состоянии \sigma. Через S обозначим множество всех состояний.

Разумеется, при рассмотрении конкретной программы \Pi нас будут интересовать значения переменных из Var_{\Pi }.

Определение 7.5. Операционная семантика программы \Pi - это отбражение (вообще говоря, частичное) типа S -> S, которое программа \Pi индуцирует на множестве всех состояний. Через \Pi (\sigma ) обозначим состояние - результат применения программы \Pi к состоянию \sigma . Оно определяется индукцией по построению программы.

  • ( x := x+1)(\sigma ) = \sigma _{1}, где \sigma _{1}(y)=\sigma (y) при y \ne  x, и \sigma _{1}(x)=\sigma (x)+1.
  • ( x := 0)(\sigma ) = \sigma _{1}, где \sigma _{1}(y)=\sigma (y) при y \ne  x, и \sigma _{1}(x)=0.
  • ( x := y)(\sigma ) = \sigma _{1}, где \sigma _{1}(z)=\sigma (z) при z \ne  x, и \sigma _{1}(x)=\sigma (y)
  • Пусть \Pi =\Pi _{1};\Pi _{2}. Тогда \Pi (\sigma )=(\Pi _{1};\Pi _{2})(\sigma )=\Pi _{2}(\Pi _{1}(\sigma )), при этом, если \Pi _{1}(\sigma )=\infty или \sigma _{1}=\Pi _{1}(\sigma ) и \Pi _{2}(\sigma _{1})=\infty, то и \Pi (\sigma )=\infty.
  • Пусть \Pi = если x = y то \Pi _{1} иначе \Pi _{2} конец. Тогда

    \Pi(\sigma)= \left\{\begin{array}{ll}
   \Pi_1(\sigma), &  \textit{если}\ \Pi_1(\sigma)< \infty \ \textit{  и }\ \sigma(x)=\sigma(y)\\
 \Pi_2(\sigma), &  \textit{если}\ \Pi_2(\sigma)< \infty \ \textit{  и }\ \sigma(x)\neq \sigma(y)\\
 \infty  &  \textit{в остальных случаях}
\end{array}
\right.
  • Пусть \Pi = если x < y то \Pi _{1} иначе \Pi _{2} конец. Тогда

    \Pi(\sigma)= \left\{\begin{array}{ll}
   \Pi_1(\sigma), &  \textit{если}\ \Pi_1(\sigma)< \infty \ \textit{  и }\ \sigma(x)<\sigma(y)\\
 \Pi_2(\sigma), &  \textit{если}\ \Pi_2(\sigma)< \infty \ \textit{  и }\ \sigma(x)\geq \sigma(y)\\
 \infty  &  \textit{в остальных случаях}
\end{array}
\right.
  • Пусть \Pi = пока x = y делай \Pi _{1} все. Тогда при \sigma (x) \ne  \sigma (y) \Pi (\sigma )= \sigma, а при \sigma (x) = \sigma (y)    \Pi (\sigma ) - это первое такое состояние \sigma _{m} в последовательности состояний \sigma _{0}=\sigma , \sigma _{1}=\Pi (\sigma _{0}),\dots , \sigma _{i+1}=\Pi (\sigma _{i}),..., что при i <= m все состояния \sigma _{i} определены, при i <m имеет место \sigma _{i}(x) = \sigma _{i}(y), и \sigma _{m}(x) \ne  \sigma _{m}(y).
  • Семантику для цикла с условием x < y определите самостоятельно (см. задачу 7.1).

Пусть \Pi - программа, Var_{\Pi  } - множество ее переменных. Выделим среди эти переменных некоторое подмножество входных переменных x1,..., xn и одну результирующую (выходную) переменную y (она может быть одной из входных). Переменные из Var_{\Pi  }, не являющиеся входными, будем называть вспомогательными.

< Лекция 6 || Лекция 7: 12 || Лекция 8 >
Алексей Семенов
Алексей Семенов
Россия, Москва, МГУПИ