Введение в схемы, автоматы и алгоритмы

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

Разбить на страницы
Показывать лекцию целиком

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

Первоначальной целью теории алгоритмов является классификация всех задач на алгоритмически разрешимые и неразрешимые, т.е. на те, для которых существуют решающие их алгоритмы, и те, для которых таких алгоритмов нет. Неформально под алгоритмом $$\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 }$$, не являющиеся входными, будем называть вспомогательными.

    Определение 7.6. Программа $$\Pi$$ с входными переменными x1,..., xn и результирующей переменной y вычисляет частичную функцию F: n -> , если для любого набора значений аргументов $$a_{1},\dots ,a_{n} (a_{i} \in )$$, она переводит начальное состояние $$\sigma,$$ в котором $$\sigma (x_{i})=a_{i}$$ при 1<= i<= n и $$\sigma (z) = 0$$ при $$z \in Var \setminus \{ x_{1},\dots ,x_{n}\}$$, в состояние $$\sigma _{1}=\Pi (\sigma )$$ тогда и только тогда, когда $$(a_{1},\dots , a_{n}) \in delta_{F}$$ и $$F(a_{1},\dots , a_{n})= \sigma _{1}(y)$$.

    Функцию, вычисляемую программой $$\Pi$$ с входными переменными x1,..., xn в (результирующей) переменной y, обозначим $$\Phi _{\Pi ,y}(x_{1}, \dots , x_{n})$$.

    Арифметическая функция F(x1, ..., xn) программно вычислима, если она вычислима некоторой программой $$\Pi$$ в некоторой переменной y при некотором разбиении переменных $$Var_{\Pi }$$ на входные: x1,..., xn и вспомогательные.

    Заметим, что в нашем языке нет понятия процедуры (подпрограммы). Для сокращения записи мы будем иногда использовать имя одной ранее написанной программы внутри текста другой: $$\Pi = \dots \Pi _{1} ..$$. Такая запись будет означать текстовую (in-line) подстановку текста (кода) программы $$\Pi _{1}$$ в соответствующее место программы $$\Pi.$$ Подчеркнем, что при этом переменные $$\Pi _{1}$$ не переименовываются и программист сам должен заботиться о правильной инициализации переменных из $$Var_{\Pi 1}$$. Например, если $$\Pi$$ использует отдельно написанную программу $$\Pi _{+}$$ из приведенного ниже примера 7.3 для сложения переменных a и b и получения результата в t, то "безопасный" и корректный способ сделать это может выглядеть так:

    $$\Pi: \ldots; x':=x; y':=y; z':=z; x:=a; y:=b;\Pi_+; t:=x; \\ x:=x'; y:=y'; z:=z'; \ldots$$

    т.е. вначале сохраняются текущие значения переменных x,y,z, используемых в $$\Pi _{+}$$, затем входным переменным x и y присваиваются нужные значения a и b и вызывается $$\Pi _{+}$$, ее результат передается в t, затем восстанавливаются значения x,y,z.

    Рассмотрим несколько примеров программ.

    Пример 7.1.

    $$\Pi _{0}: x := 0$$

    Ясно, что $$\Phi _{\Pi 0,x} (x)$$ тождественно равна 0.

    Пример 7.2.

    $$\Pi _{1}: x := x+1$$

    А здесь $$\Phi _{\Pi 1,x}(x)= x+1$$ для любого x.

    Пример 7.3.

    $$\Pi _{+}: пока \ z < y \ делай \ z:=z+1; x := x+1 \ все$$

    Зафиксируем входные переменные x, y и выходную переменную x ( z - рабочая переменная ). Легко показать, что $$\Phi _{\Pi +,x}(x,y)= x+y$$.

    Действительно, при y=0 тело цикла не выполняется и выход равен x=x+0. При y >= 1 тело цикла выполняется y раз и при каждом его выполнении x увеличивается на 1.

    Пример 7.4.

    $$\Pi_4(n,i):\\ x_1 := x_1;\ldots ; x_n:= x_n; x_1:= x_i$$

    $$\Pi _{4}(n,i)$$ вычисляет в x1 функцию выбора i-го аргумента: $$\Phi_{\Pi 4}(n,i), x_1(x_1, ... , x_n)= x_i$$.

    Пример 7.5.

    $$\Pi_5(n):\\ x_1 := x_1;\ldots ; x_n:= x_n; \mbox{пока}\ x_1=x_1\ \mbox{делай}\ x_1:=x_1 \mbox{все}$$

    Нетрудно понять, что $$\Pi _{5}(n)$$ вычисляет нигде не определенную функцию от n переменных: $$\Phi_{\Pi 5}(n), x_1(x_1, ... , x_n)= \infty$$.

    Задачи

    Задача 7.1. Определите (по аналогии с п. (ж)) определения 7.5 семантику для программ вида

    $$\Pi =$$ пока x < y делай $$\Pi _{1}$$ все.

    Задача 7.2.Построить структурированные программы, вычисляющие в z следующие функции, и доказать их корректность:

  • f{x}(x,y)= x*y;
  • ffact(x)= x!;
  • f-1(x)= x $$dot{-}$$ 1, где 0 $$dot{-}$$ 1 = 0 и (x+1) $$dot{-}$$ 1 = x ;
  • f-(x,y)= x $$dot{-}$$ y, где x $$dot{-}$$ y = x-y, если x >= y и x $$dot{-}$$ y=0, если x < y ;
  • fsqr(x)= [sqrt x];
  • fexp(x)= 2x;
  • flog(x)= [log2x];
  • f/(x,y)= [x/y].
  • Задача 7.3. Пусть $$\Pi$$ - структурированная программа и $$|Var_{\Pi }| = m$$. Из определений следует, что при различной фиксации входных переменных и выходной переменной программа может вычислять различные функции.

  • Каково максимальное число функций от n <= m переменных, которое может вычислять $$\Pi?$$ Сколько всего разных функций может вычислить $$\Pi?$$
  • Постройте программу $$\Pi (m,n)$$, которая вычисляет максимальное число различных функций от n <= m переменных.
  • Постройте программу $$\Pi (m)$$ с $$|Var_{\Pi }| = m$$, которая для каждого n <= m вычисляет максимальное число различных функций от n переменных.
  • Задача 7.4.Построить структурированные программы, вычисляющие в z следующие функции:

  • $$\begin{array}{lll} f_1(x, y) = \left \{\begin{array}{ll} x^2y^3, \text{ если $x < y$ } \\ \text{} [ (x+y)/2 ] , \text{ в противном случае} \end{array} \right. \\ \end{array}$$
  • $$\begin{array}{lll} f_2(x, y) = \left \{\begin{array}{ll} 3^y, \text{ если $\log_2 (x+1) \geq y$ }\\ |x -y|, \mbox{ в противном случае} \end{array} \right.\\ \end{array}$$
  • $$\begin{array}{lll} f_3(x, y) = \left \{\begin{array}{ll} [x*y/2], \text{ если $\log_2 x \leq y+2$ }\\ x^{[y/2], \mbox{ в противном случае} \end{array} \right. \\ \end{array}$$
  • $$\begin{array}{lll} p(x) = \left \{\begin{array}{ll} 1, \ \ \ \mbox{ если $x$ --- простое число}\\ 0, \ \ \ \mbox{ в противном случае} \end{array} \right. \end{array}$$
  • Задача 7.5. Пусть структурированная программа $$\Pi$$ вычисляет в переменной y некоторую всюду определенную взаимно однозначную функцию f(x), область значений которой совпадает с множеством всех натуральных чисел N. Пусть $$Var_{\Pi }=\{ x, y, z_{1},\dots , z_{m}\}$$. Постройте структурированную программу, которая вычисляет обратную функцию f-1(x) = { z | f(z)=x}.

    Задача 7.6. Пусть F(x) задана соотношениями F(0)=1, F(1)=1, F(x+2)= F(x)+F(x+1) (элементы последовательности F(x) называются числами Фибоначчи). Постройте структурированную программу, которая вычисляет функцию F(x).

    Страницы:

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

    Первоначальной целью теории алгоритмов является классификация всех задач на алгоритмически разрешимые и неразрешимые, т.е. на те, для которых существуют решающие их алгоритмы, и те, для которых таких алгоритмов нет. Неформально под алгоритмом $$\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 }$$, не являющиеся входными, будем называть вспомогательными.

    Определение 7.6. Программа $$\Pi$$ с входными переменными x1,..., xn и результирующей переменной y вычисляет частичную функцию F: n -> , если для любого набора значений аргументов $$a_{1},\dots ,a_{n} (a_{i} \in )$$, она переводит начальное состояние $$\sigma,$$ в котором $$\sigma (x_{i})=a_{i}$$ при 1<= i<= n и $$\sigma (z) = 0$$ при $$z \in Var \setminus \{ x_{1},\dots ,x_{n}\}$$, в состояние $$\sigma _{1}=\Pi (\sigma )$$ тогда и только тогда, когда $$(a_{1},\dots , a_{n}) \in delta_{F}$$ и $$F(a_{1},\dots , a_{n})= \sigma _{1}(y)$$.

    Функцию, вычисляемую программой $$\Pi$$ с входными переменными x1,..., xn в (результирующей) переменной y, обозначим $$\Phi _{\Pi ,y}(x_{1}, \dots , x_{n})$$.

    Арифметическая функция F(x1, ..., xn) программно вычислима, если она вычислима некоторой программой $$\Pi$$ в некоторой переменной y при некотором разбиении переменных $$Var_{\Pi }$$ на входные: x1,..., xn и вспомогательные.

    Заметим, что в нашем языке нет понятия процедуры (подпрограммы). Для сокращения записи мы будем иногда использовать имя одной ранее написанной программы внутри текста другой: $$\Pi = \dots \Pi _{1} ..$$. Такая запись будет означать текстовую (in-line) подстановку текста (кода) программы $$\Pi _{1}$$ в соответствующее место программы $$\Pi.$$ Подчеркнем, что при этом переменные $$\Pi _{1}$$ не переименовываются и программист сам должен заботиться о правильной инициализации переменных из $$Var_{\Pi 1}$$. Например, если $$\Pi$$ использует отдельно написанную программу $$\Pi _{+}$$ из приведенного ниже примера 7.3 для сложения переменных a и b и получения результата в t, то "безопасный" и корректный способ сделать это может выглядеть так:

    $$\Pi: \ldots; x':=x; y':=y; z':=z; x:=a; y:=b;\Pi_+; t:=x; \\ x:=x'; y:=y'; z:=z'; \ldots$$

    т.е. вначале сохраняются текущие значения переменных x,y,z, используемых в $$\Pi _{+}$$, затем входным переменным x и y присваиваются нужные значения a и b и вызывается $$\Pi _{+}$$, ее результат передается в t, затем восстанавливаются значения x,y,z.

    Рассмотрим несколько примеров программ.

    Пример 7.1.

    $$\Pi _{0}: x := 0$$

    Ясно, что $$\Phi _{\Pi 0,x} (x)$$ тождественно равна 0.

    Пример 7.2.

    $$\Pi _{1}: x := x+1$$

    А здесь $$\Phi _{\Pi 1,x}(x)= x+1$$ для любого x.

    Пример 7.3.

    $$\Pi _{+}: пока \ z < y \ делай \ z:=z+1; x := x+1 \ все$$

    Зафиксируем входные переменные x, y и выходную переменную x ( z - рабочая переменная ). Легко показать, что $$\Phi _{\Pi +,x}(x,y)= x+y$$.

    Действительно, при y=0 тело цикла не выполняется и выход равен x=x+0. При y >= 1 тело цикла выполняется y раз и при каждом его выполнении x увеличивается на 1.

    Пример 7.4.

    $$\Pi_4(n,i):\\ x_1 := x_1;\ldots ; x_n:= x_n; x_1:= x_i$$

    $$\Pi _{4}(n,i)$$ вычисляет в x1 функцию выбора i-го аргумента: $$\Phi_{\Pi 4}(n,i), x_1(x_1, ... , x_n)= x_i$$.

    Пример 7.5.

    $$\Pi_5(n):\\ x_1 := x_1;\ldots ; x_n:= x_n; \mbox{пока}\ x_1=x_1\ \mbox{делай}\ x_1:=x_1 \mbox{все}$$

    Нетрудно понять, что $$\Pi _{5}(n)$$ вычисляет нигде не определенную функцию от n переменных: $$\Phi_{\Pi 5}(n), x_1(x_1, ... , x_n)= \infty$$.

    Задачи

    Задача 7.1. Определите (по аналогии с п. (ж)) определения 7.5 семантику для программ вида

    $$\Pi =$$ пока x < y делай $$\Pi _{1}$$ все.

    Задача 7.2.Построить структурированные программы, вычисляющие в z следующие функции, и доказать их корректность:

  • f{x}(x,y)= x*y;
  • ffact(x)= x!;
  • f-1(x)= x $$dot{-}$$ 1, где 0 $$dot{-}$$ 1 = 0 и (x+1) $$dot{-}$$ 1 = x ;
  • f-(x,y)= x $$dot{-}$$ y, где x $$dot{-}$$ y = x-y, если x >= y и x $$dot{-}$$ y=0, если x < y ;
  • fsqr(x)= [sqrt x];
  • fexp(x)= 2x;
  • flog(x)= [log2x];
  • f/(x,y)= [x/y].
  • Задача 7.3. Пусть $$\Pi$$ - структурированная программа и $$|Var_{\Pi }| = m$$. Из определений следует, что при различной фиксации входных переменных и выходной переменной программа может вычислять различные функции.

  • Каково максимальное число функций от n <= m переменных, которое может вычислять $$\Pi?$$ Сколько всего разных функций может вычислить $$\Pi?$$
  • Постройте программу $$\Pi (m,n)$$, которая вычисляет максимальное число различных функций от n <= m переменных.
  • Постройте программу $$\Pi (m)$$ с $$|Var_{\Pi }| = m$$, которая для каждого n <= m вычисляет максимальное число различных функций от n переменных.
  • Задача 7.4.Построить структурированные программы, вычисляющие в z следующие функции:

  • $$\begin{array}{lll} f_1(x, y) = \left \{\begin{array}{ll} x^2y^3, \text{ если $x < y$ } \\ \text{} [ (x+y)/2 ] , \text{ в противном случае} \end{array} \right. \\ \end{array}$$
  • $$\begin{array}{lll} f_2(x, y) = \left \{\begin{array}{ll} 3^y, \text{ если $\log_2 (x+1) \geq y$ }\\ |x -y|, \mbox{ в противном случае} \end{array} \right.\\ \end{array}$$
  • $$\begin{array}{lll} f_3(x, y) = \left \{\begin{array}{ll} [x*y/2], \text{ если $\log_2 x \leq y+2$ }\\ x^{[y/2], \mbox{ в противном случае} \end{array} \right. \\ \end{array}$$
  • $$\begin{array}{lll} p(x) = \left \{\begin{array}{ll} 1, \ \ \ \mbox{ если $x$ --- простое число}\\ 0, \ \ \ \mbox{ в противном случае} \end{array} \right. \end{array}$$
  • Задача 7.5. Пусть структурированная программа $$\Pi$$ вычисляет в переменной y некоторую всюду определенную взаимно однозначную функцию f(x), область значений которой совпадает с множеством всех натуральных чисел N. Пусть $$Var_{\Pi }=\{ x, y, z_{1},\dots , z_{m}\}$$. Постройте структурированную программу, которая вычисляет обратную функцию f-1(x) = { z | f(z)=x}.

    Задача 7.6. Пусть F(x) задана соотношениями F(0)=1, F(1)=1, F(x+2)= F(x)+F(x+1) (элементы последовательности F(x) называются числами Фибоначчи). Постройте структурированную программу, которая вычисляет функцию F(x).

    Вернуться к учебному плану