Преобразователь предикатов.

advertisement
Министерство РФ по связи и информатизации
Поволжская государственная академия телекоммуникаций
и информатики
Кафедра программного обеспечения информационных технологий
Методические указания
к практическим занятиям
по курсу «Теория вычислительных
процессов»
Составители:
Зав. кафедры ПОИТ,
д.т.н. проф.
Асс. кафедры ПОИТ
Рецензент:
Д.ф.-м.н. проф.
Самара
2004
Солодянников Ю.В.
Мастюгин Д.Е.
Блатов И.А.
СОДЕРЖАНИЕ
Введение ............................................................................................ 3
Практическое занятие №1
«Стандартные схемы программ» .................................................... 4
Практическое занятие №2
«Рекурсивные схемы» .................................................................... 14
Практическое занятие №3
«Аксиоматическая семантика. Определение слабейших
предусловий операторов» .............................................................. 21
Практическое занятие №4
«Верификация программ».............................................................. 31
Практическое занятие №5
«Моделирование систем на основе сетей Петри» ....................... 41
2
Введение
В данном методическом пособии рассматриваются основные
вопросы курса «Теория вычислительных процессов»: построение
стандартных и рекурсивных схем программ, аксиоматическая
семантика и определение слабейших предусловий операторов,
верификация программ, а также моделирование систем на основе
сетей Петри.
Пособие предназначено для выполнения практических занятий
по курсу «Теория вычислительных процессов» студентами
специальности 220400 – «Программное обеспечение вычислительной
техники и автоматизированных систем».
3
Практическое занятие №1
«Стандартные схемы программ»
1. Цель занятия
Изучение стандартных схем, способов их построения,
реализация соответствующих интерпретаций. Выполнение программы
и создание протокола выполнения программы.
2. Литература
 Ершов А.П. Введение в теоретическое программирование. М.:
Наука, 1977.
 Котов В.Е . Введение в теорию схем программ. Новосибирск.:
Наука, 1978. -258с.
 Котов В.Е., Сабельфельд В.К. Теория схем программ. М: Наука,
Гл. ред. физ.-мат. лит., 1991. -248с.
3. Выполнение работы
 Изучить:
 состав базиса класса стандартных схем программ;
 графовую форму стандартной схемы;
 линейную форму стандартной схемы;
 интерпретации стандартных схем программ.

 построить базис стандартной схемы;
 реализовать стандартную схему в графовой и линейной формах;
 составить интерпретацию для заданной стандартной схемы;
 составить протокол выполнения программы;
 составить отчет по проделанной работе в соответствии с
требованиями, предъявляемыми в пункте 6 данного практического
занятия.
4. Контрольные вопросы
1. Что такое схема программы? Чем отличается схема программы от
программы?
2. Из каких частей стандартная схема программы?
3. Какие множества составляют полный базис класса стандартных
схем?
4. Что такое термы и тесты? В чем разница между ними?
4
5. Из каких видов вершин состоит граф стандартной схемы
программ?
6. Что такое линейная форма стандартной схемы программ?
7. Что называют интерпретацией базиса в области интерпретации?
8. Что такое конфигурация программы?
9. Для чего служит протокол выполнения программы? В каком
случае программа считается остановившейся?
5. Содержание работы
 Ознакомиться с кратким теоретическим материалом, ответить на
контрольные вопросы;
 определить номер выполняемого варианта;
 для заданного варианта построить стандартную схему:
 построить полный базис стандартной схемы;
 реализовать стандартную схему в графовой и линейной
формах;
 для полученной стандартной схемы программ реализовать
соответствующую интерпретацию;
 для заданного варианта выполнить программу. Результат
выполнения программы необходимо отразить в протоколе
выполнения программы.
6. Содержание отчета
Отчет должен содержать следующее:
 титульный лист с указанием наименования и цели занятия;
фамилии, имени, отчества и номера группы студента; фамилии,
имени, отчества преподавателя, а также номер выполняемого
варианта;
 дату выполнения работы;
 цель занятия;
 условия предложенной задачи;
 построенную стандартную схему программ (полный базис,
реализации в графовой и линейной формах);
 реализацию соответствующей интерпретации;
 протокол выполнения программы;
 выводы о проделанной работе.
5
7. Краткий теоретический материал
Программы и схемы программ
Схемы программ - это математические модели программ,
описывающие строение программы, или точнее строение множества
программ, где конкретные операции и функции заменены
абстрактными функциональными и предикатными символами.
Следующий пример программ вычисления факториала n! и
переворачивания слов поясняет различие между программами и их
схемой S1.
begin integer x, y;
ввод(x);
y:=1;
L: if x=0 then goto L1;
y:=x*y
x:=x-1;
goto L;
L1: вывод(y);
end
begin integer x, y;
ввод(x);
y:=ε;
L: if x=0 then goto L1;
y:=CONSCAR(x, y);
x:=CDR(x);
goto L;
L1: вывод(y);
End
begin
ввод(x);
y:=a;
L: if p(x) then goto L1;
y:=g(x, y);
x:=h(x);
goto L;
L1: вывод(y);
end
Функция CONSCAR (суперпозиция функций CONS и CAR из
языка Лисп) приписывает первую букву первого слова ко второму
слову (т. е. CONSCAR(аб, в) = ав), а функция CAR стирает первую
букву слова (т. е. CAR(аб) = б).
Стандартные схемы программ
Базис класса стандартных схем программ
Стандартные схемы программ (ССП) характеризуются базисом
и структурой схемы.
Базис класса фиксирует символы, из которых строятся схемы,
указывает их роль (переменные, функциональные символы и др.),
задает вид выражений и операторов схем.
Полный базис В класса стандартных схем состоит из 4-х
непересекающихся, счетных множеств символов и множества
операторов - слов, построенных из этих символов.
Множества символов полного базиса:
1. Х = {x, х1, х2..., у, у1 у2..., z, z1, z2...} - множество символов,
называемых переменными;
2. F = {f(0), f(1), f(2)..., g(0), g(1), g(2)..., h(0), h(1), h(2)...} - множество
функциональных символов; верхний символ задает местность
6
символа; нульместные символы называют константами и
обозначают начальными буквами латинского алфавита a, b,
c...;
3. Р = {р(0), р(1), р(2)...; q(0), q(1), q(2)...; } - множество предикатных
символов; р(0), q(0) - ; нульместные символы называют
логическими константами;
4. {start, stop, ...,:= и т. д.} - множество специальных символов.
Термами (функциональными выражениями) называются слова,
построенные из переменных, функциональных и специальных
символов по следующим правилам:
1. односимвольные слова, состоящие из переменных или
констант, являются термами;
2. слово τ вида f(n)(τ1, τ2...τn), где τ1, τ2...τn - термы, является
термом;
Примеры термов: х, f(0), а, f(1)(х), g(2)(x, h(3)(y, a)).
Тестами (логическими выражениями) называются логические
константы и слова вида р(n)(τ1, τ2,...,τn). Примеры: p(0), p(0)(х), g(3)(x, y,
z), p(2) (f(2(x, y)). Допускается в функциональных и логических
выражениях опускать индексы местности, если это не приводит к
двусмысленности или противоречию.
Множество операторов включает пять типов:
1. начальный оператор - слово вида start(х1, х2...хк), где k ≥0, а х1,
х2...хк - переменные, называемые результатом этого оператора;
2. заключительный оператор - слово вида stop(τ1, τ2...τn), где n
≥0, а τ1, τ2...τn - термы; вхождения переменных в термы τ
называются аргументами этого оператора;
3. оператор присваивания - слово вида х := τ, где х – переменная
(результат оператора), а τ - терм; вхождения переменных в
термы называются аргументами этого оператора;
4. условный оператор (тест) - логическое выражение; вхождения
переменных
в
логическое
выражение
называются
аргументами этого оператора;
5. оператор петли - односимвольное слово loop.
Среди операторов присваивания выделим случаи: когда τ переменная, то оператор называется пересылкой (х:=у) и когда τ константа, то оператор называется засылкой (х:=а).
Подклассы используют ограниченные базисы. Так, например,
подкласс У1 имеет базис:
7
х1, х2, а, f(1), p(1), start, stop, (,),:=, ,и множество операторов
start(х1, х2); х1:= f(x1), x2=f(x2), x1:=а, х2:= а, р(х1), р(х2), stop(х1,х2), т.
е. схемы из этого подкласса используют две переменные, константу а,
один одноместный функциональный символ, один предикатный
символ и операторы указанного вида.
Графовая форма стандартной схемы
Представим стандартную схему программ как размеченный
граф, вершинам которого приписаны операторы из некоторого базиса
В.
Стандартной схемой
в базисе В называется конечный
(размеченный ориентированный) граф без свободных дуг и с
вершинами следующих пяти видов:
1. Начальная вершина (ровно одна) помечена начальным
оператором. Из нее выходит ровно одна дуга. Нет дуг,
ведущих к начальной вершине.
2. Заключительная вершина (может быть несколько). Помечена
заключительным оператором. Из нее не выходит ни одной
дуги.
3. Вершина-преобразователь.
Помечена
оператором
присваивания. Из нее выходит ровно одна дуга.
4. Вершина-распознаватель. Помечена условным оператором
(называемым условием данной вершины). Из нее выходит
ровно две дуги, помеченные 1 (левая) и 0 (правая).
5. Вершина-петля. Помечена оператором петли. Из нее не
выходит ни одной дуги.
Конечное множество переменных схемы S составляют ее память
ХS.
Из определения следует, что один и тот же оператор может
помечать несколько вершин схемы.
Вершины именуются (метки вершины) целым неотрицательным
числом (0, 1, 2...). Начальная вершина всегда помечается меткой 0.
Схема S называется правильной, если на каждой дуге заданы все
переменные.
Пример правильной ССП S1 в графовой форме приведен на
рисунке 1.
Вершины изображены прямоугольниками, а вершинараспознаватель - овалом. Операторы записаны внутри вершины.
8
Линейная форма стандартной схемы
Для использования линейной формы СПП множество
специальных символов расширим дополнительными символами :,
goto, if, then, else. СПП в линейной форме представляет собой
последовательность инструкций, которая строится следующим
образом:
start(x)
1
y:= a
2
p(x)
1
stop(y)
5
0
3 y:=g(x,
y)
4 x:= h(x)
Рис.1.1 Графовая форма стандартной схемы
1. если выходная дуга начальной вершины с оператором start(х1,...,
хn) ведет к вершине с меткой L, то начальной вершине
соответствует инструкция:
0: start(х1,..., хn) goto L;
2. если вершина схемы S с меткой L - преобразователь с оператором
присваивания х:=τ, выходная дуга которого ведет к вершине с
меткой L1, то этому преобразователю соответствует инструкция:
L: x: =τ goto L1;
3. если вершина с меткой L - заключительная вершина с оператором
stop(τ1,...τm), то ей соответствует инструкция
9
L: stop(τ1,..., τm);
4. если вершина с меткой L - распознаватель с условием р(τ1,...τk),
причем 1-дуга ведет к вершине с меткой L1, а 0-дуга - к вершине с
меткой L0, то этому распознавателю соответствует инструкция
L: if р(τ1,...τk) then L1 else L0;
5. если вершина с меткой L - петля, то ей соответствует инструкция
L: loop.
Обычно используется сокращенная запись (опускание меток).
Полная и сокращенная линейные формы ССП (Рис. 1.1) приведены
ниже:
0: start(х) goto 1,
1: у: = а goto 2,
2: if р(х) then 5 else 3,
3: у: = g(x,y) goto 4,
4: х: = h(x) goto 2,
5: stop(у).
start(х),
у: = а,
2: if р(х) then 5 else 3,
3: у: = g(x,y),
х: = h (x) goto 2,
5: stop(у).
Интерпретация стандартных схем программ
ССП не является записью алгоритма, поэтому позволяет
исследовать только структурные свойства программ, но не семантику
вычислений. При построении «семантической» теории схем программ
вводится понятие интерпретация ССП. Определим это понятие.
Пусть в некотором базисе В определен класс ССП.
Интерпретацией базиса В в области интерпретации D называется
функция I, которая сопоставляет:
1.
каждой переменной х из базиса В - некоторый элемент d =
I(x) из области интерпретации D;
2.
каждой константе а из базиса В - некоторый элемент d =
I(а) из области интерпретации D;
3.
каждому функциональному символу f(n) - всюду
определенную функцию F(n)=I(f(n));
4.
каждой логической константе р(0) - один символ множества
{ 0,1 };
5.
каждому предикатному символу р(n) - всюду определенный
предикат P(n) = I(p(n)).
Пара (S,I) называется интерпретированной стандартной
схемой (ИСС), или стандартной программой (СП).
Определим понятие выполнения программы.
10
Состоянием памяти программы (S,I) называют функцию W: XS
 D, которая каждой переменной x из памяти схемы S сопоставляет
элемент W(x) из области интерпретации D.
Значение терма τ при интерпретации I и состоянии памяти W
(обозначим τI(W)) определяется следующим образом:
1) если τ=х, x – переменная, то τI(W) = W(x);
2) если τ=a, a – константа, то τI(W) = I(a);
3) если τ=f(n)(τ1, τ2..., τn), то τI(W)= I(f(n))(τ1I(W), τ2I(W),..., τnI(W)).
Аналогично определяется значение теста  при интерпретации I
и состоянии памяти W или I(W):
если =р(n)(τ1, τ2..., τn), то I(W)= I(p(n))(τ1I(W), τ2I(W),... τnI(W)),
n ≥0.
Конфигурацией программы называют пару U=(L,W), где L метка вершины схемы S, а W - состояние ее памяти. Выполнение
программы
описывается
конечной
или
бесконечной
последовательностей конфигураций, которую называют протоколом
выполнения программы (ПВП).
Протокол (U0, U1,..., Ui, Ui+1,...) выполнения программы (S,I)
определяем следующим образом (ниже ki означает метку вершины, а
Wi - состояние памяти в i-й конфигурации протокола, Ui=(ki,Wi)):
U0=(0, W0), W0 – начальное состояние памяти схемы S при
интерпретации I.
Пусть Ui=(ki, Wi) - i-я конфигурация ПВП, а О - оператор схемы
S в вершине с меткой ki. Если О - заключительный оператор stop(τ1,
τ2... τn), то Ui - последняя конфигурация, так что протокол конечен. В
этом случае считают, что, программа (S,I) останавливается, а
последовательность значений τ1I(W), τ2I(W),..., τnI(W) объявляют
результатом val(S,I) выполнения программы (S,I). В противном
случае, т. е. когда О - не заключительный оператор, в протоколе
имеется следующая, (i+1)-я конфигурация
Ui+1 = (ki+1, Wi+1),
причем
а) если О - начальный оператор, а выходящая из него дуга
ведет к вершине с меткой L, то ki+1 = L и Wi+1 = Wi;
б) если О - оператор присваивания х:=τ, а выходящая из него
дуга ведет к вершине с меткой L, то ki+1 = L, Wi+1 = Wi, Wi+1(х) = τ1(Wi);
в) если О - условный оператор  и I(Wi) = Δ, где Δ 0,1, а
выходящая из него дуга ведет к вершине с меткой L, то ki+1 = L и Wi+1
= Wi;
11
г) если О - оператор петли, то ki+1 = L и Wi+1 = Wi, так что
протокол бесконечен.
Таким образом, программа останавливается тогда и только
тогда, когда протокол ее выполнения конечен. В противном случае
программа зацикливается и результат ее выполнения не определен.
Рассмотрим две интерпретации СПП S1 (Рис. 1.1).
Интерпретация (S1, I1) задана так:
 область интерпретации D1  Nat - подмножество множества
Nat целых неотрицательных чисел;
 I1(x)=4; I1(y)=0; I1(a)=1;
 I1(g)=G, где G - функция умножения чисел, т. е. G(d1,d2)=
d1*d2;
 I1(h)=H, где H - функция вычитания единицы, т. е. H(d)= d-1;
 I1(p)=P1, где P1 - предикат «равно 0», т.е. P1(d)=1, если d=0.
Программа (S1, I1) вычисляет 4! (Рис. 1.1).
ПВП (S1, I1) конечен, результат - 24 (Таб. 1.1).
Таблица 1.1
Конфигурация U0
Метка
0
Значения х
4
у
0
U1 U2 U3 U4 U5 U6 U7 U8 U9 U10
1 2 3 4 2 3 4 2 3 4
4 4 4 3 3 3 2 2 2 1
1 1 4 4 4 12 12 12 24 24
U11
2
1
24
U12 U13
5
1 0
24 24
8. Номер варианта
0
1
7
3
Последняя цифра зачетной книжки
2
3
4
5
6
7
Номер варианта
4
9
1
8
2
5
8
9
6
10
9. Варианты заданий
Номер
Действия, выполняемые
варианта
программой
1
Расчет суммы членов
арифметической
прогрессии. Разность
арифметической
прогрессии d=3
12
Пример для выполнения
программы
Расчет суммы первых пяти
членов арифметической
прогрессии
2
3
4
5
6
7
8
9
10
Расчет суммы первых
членов геометрической
прогрессии. Знаменатель
прогрессии q=2
Расчет чисел Фибоначчи
Расчет произведения
членов арифметической
прогрессии. Разность
арифметической
прогрессии d=2
Расчет произведения
первых членов
геометрической
прогрессии. Знаменатель
прогрессии q=4
Расчет суммы чисел
Фибоначчи
Расчет произведения чисел
Фибоначчи
Решение квадратного
уравнения
Нахождение наименьшего
общего кратного двух
чисел
Нахождение наибольшего
общего делителя
(алгоритм Евклида)
13
Расчет суммы первых пяти
членов геометрической
прогрессии
Расчет седьмого числа
Фибоначчи
Расчет произведения
первых четырех членов
арифметической
прогрессии
Расчет произведения
первых четырех членов
геометрической прогрессии
Расчет суммы первых
четырех чисел Фибоначчи
Расчет произведения
первых четырех чисел
Фибоначчи
Решить квадратное
уравнение x 2  5 x  4  0
Найти наименьшее общее
кратное чисел: 2 и 3
Найти наибольший общий
делитель чисел: 45 и 72
Практическое занятие №2
«Рекурсивные схемы»
1. Цель занятия
Изучение рекурсивных схем, рекурсивных уравнений,
соответствующих им интерпретаций. Выполнение программы и
создание протокола выполнения программы.
2. Литература
 Ершов А.П. Введение в теоретическое программирование. М.:
Наука, 1977.
 Котов В.Е . Введение в теорию схем программ. Новосибирск.:
Наука, 1978. -258с.
 Котов В.Е., Сабельфельд В.К. Теория схем программ. М: Наука,
Гл. ред. физ.-мат. лит., 1991. -248с.
3. Выполнение работы
 Изучить:
 состав полного базиса рекурсивных схем;
 интерпретации рекурсивных схем.
 построить базис рекурсивной схемы;
 составить интерпретацию для заданной рекурсивной схемы;
 составить протокол выполнения программы;
 составить отчет по проделанной работе в соответствии с
требованиями, предъявляемыми в пункте 6 данного практического
занятия.
4. Контрольные вопросы
1. В чем разница между операторным программированием и
рекурсивным?
2. Какие операторные и рекурсивные языки программирования Вам
известны?
3. Из чего состоит полный базис рекурсивной схемы?
4. Чем отличается базис стандартной схемы программ от базиса
рекурсивной схемы?
5. Что такое логическое выражение?
6. Что такое термы?
7. Что такое рекурсивное уравнение?
8. Дайте определение рекурсивной схемы.
14
5. Содержание работы
 Ознакомиться с кратким теоретическим материалом, ответить на
контрольные вопросы;
 определить номер выполняемого варианта;
 для заданного варианта построить рекурсивную схему:
 базис рекурсивной схемы;
 рекурсивные уравнения:
 для
полученной
рекурсивной
схемы
реализовать
соответствующую интерпретацию;
 для заданного варианта выполнить программу. Результат
выполнения программы необходимо отразить в протоколе
выполнения программы.
6. Содержание отчета
Отчет должен содержать следующее:
 титульный лист с указанием наименования и цели занятия;
фамилии, имени, отчества и номера группы студента; фамилии,
имени, отчества преподавателя, а также номер выполняемого
варианта;
 дату выполнения работы;
 цель занятия;
 условия предложенной задачи;
 построенную рекурсивную схему (полный базис, рекурсивные
уравнения);
 реализацию соответствующей интерпретации;
 протокол выполнения программы;
 выводы о проделанной работе.
7. Краткий теоретический материал
Рекурсивные схемы
Рекурсивное программирование
Среди упомянутых выше методов формализации понятия
вычислимой функции метод Тьюринга — Поста основан на уточнении
понятия процесса вычислений, для чего используются абстрактные
«машины», описанные в точных математических терминах. Другой
подход (метод Черча — Клини) основан на понятии рекурсивной
функции, рекурсивная функция задается с помощью рекурсивных
15
определений. Рекурсивное определение позволяет связать искомое
значение функции для заданных аргументов с известными значениями
той же функции при некоторых других аргументах. Эта связь
устанавливается с помощью универсального механизма рекурсии,
дающего механическую процедуру поиска значений функции. Двум
подходам к определению вычислимых функций соответствуют два
метода программирования этих функций — операторное и
рекурсивное программирование. При операторном методе программа
представляет собой явно выписанную последовательность, описаний
действий
гипотетической
вычислительной
машины
(последовательность операторов, команд и т. п.).
Язык Фортран — типичный представитель операторных языков.
С другой стороны, рекурсивная программа — это совокупность
рекурсивных определений, задающих рекурсивную функцию, для
которой аргументами служат начальные данные программы, а
значением — результат выполнения программы. Известный язык
рекурсивного программирования — язык Лисп — предназначен для
обработки символьной информации. В других зыках комбинируют
оба метода программирования. Так, Паскаль — операторный язык с
возможностью рекурсивного программирования, предоставляемой
механизмом рекурсивных процедур и функций.
Примером рекурсивно определяемой функции является
факториальная функция FACT: Nat → Nat:
FACT(х) = 1,если х = 0, FACT(х)=хFACT(х — 1), если х >0.
Эту же функцию можно запрограммировать в некотором
рекурсивном языке, базирующемся на механизме рекурсивных
функций языка Паскаль:
FACT(a),
FACT(х) = if х = 0 then 1 else х  FACT(х - 1),
где а — некоторое целое неотрицательное число.
Выполнение этой программы для некоторого значения а (пусть
а=4) может быть осуществлено следующим образом. В обе части
рекурсивного определения вместо х подставляется 4, после чего
вычисляется правая часть определения. Вычисление правой части
начинается с вычисления логического выражения. Если его значение 1
(истина), то вычисляется левое функциональное выражение (стоящее
после then), а если его значение 0 (ложь) — вычисляется правое
выражение (стоящее после else). Вычисление функционального
выражения сводится к его упрощению, т. е. выполнению всех
16
возможных вычислений. Если в упрощенном выражения остается
вхождение символа определяемой функции FACT, то осуществляется
переход к новому шагу выполнения программы. На этом шаге
вхождение FACT(m), где m — значение внутри скобок после
упрощения, заменяется левым (т = 0) или правым (m > 0)
функциональным выражением, в котором все вхождения х заменены
на m. Упрощения продолжаются до тех пор, пока не будет получено
выражение, не содержащее FACT (в нашем случае это выражение —
число).
Вычисление рекурсивной программы может завершиться за
конечное число шагов с результатом, равным значению
запрограммированной функции для заданных аргументов (начальных
значений переменных), но может и продолжаться бесконечно. В
последнем случае значение функции не определено.
Определение рекурсивной схемы
Рекурсивная схема (РС) так же, как СПП определяется в
некотором базисе. Полный базис РС, как и базис ССП, включает
четыре счетных множества символов: переменные, функциональные
символы, предикатные символы, специальные символы.
Множества переменных и предикатных символов ничем не
отличаются от ССП. Множество специальных символов - другое, а
именно: {if, то, else, (, ), ,}. Отличие множества функциональных
символов состоит в том, что оно разбито на два непересекающиеся
подмножества: множество базовых функциональных символов и
множество определяемых функциональных символов (обозначаются
для отличия прописными буквами, например, F(1),G(2), и т.д.).
В базисе РС нет множества операторов, вместо него –
множество логических выражений и множество термов.
Простые термы определяются так же, как термы–выражения
в СПП. Среди простых термов выделим базовые термы, которые не
содержат определяемых функциональных символов, а также вызовытермы вида F(n)(1,2,…n), где 1,2,… n - простые термы, F(n) определяемый функциональный символ.
Логическое выражение - слово вида
p(n)(1,2,…n),
где p(n) - предикатный символ, а 1,2,…n - базовые термы.
Терм - это простой терм, или условный терм, т.е. слово вида
if  then 1 else 2,
17
где  - логическое выражение, 1, 2 - простые термы, называемые
левой и соответственно правой альтернативой.
Примеры термов:
− f(x, g(x, y)); h(h(a)) - базовые термы;
− f(F(x), g(x, F(y))); H(H(a)) - простые термы;
− F(x); H(H(a)) - вызовы;
− if p(x, y) then h(h(a)) else F(x) - условный терм.
Используется бесскобочная форма представления:
if pxy then hha else Fx - условный терм.
Расширим в базисе В множество специальных символов
символом "=".
Рекурсивным уравнением, или определением функции F
назовем слово вида
F(n)(x1,x2,…xn) = (x1,x2,…xn),
где (x1,x2,…xn) - терм, содержащий переменные, называемые
формальными параметрами функции F.
Рекурсивной схемой называется пара (, М), где  - терм,
называемый главным термом схемы (или ее входом). М - такое
множество рекурсивных уравнений, что все определяемые
функциональные символы в левых частях уравнений различны и
всякий определяемый символ, встречающийся в правой части
некоторого уравнения или в главном терме схемы, входит в левую
часть некоторого уравнения. Другими словами, в РС имеется
определение всякой вызываемой в ней функции, причем ровно одно.
Примеры РС:
RS1: F(x); F(x) = if p(x) then a else g(x, F(h(x))).
RS2: A(b, c); A(x, y) = if p(x) then f(x) else B(x, y);
B(x, y) = if p(y) then A(g(x), a) else C(x, y);
C(x, y) = A(g(x), A(x, g(y))).
RS3: F(x); F(x) = if p(x) then x else f(F(g(x)), F(h(x))).
Пара (RS, I), где RS - PC в базисе В, а I - интерпретация этого
базиса, называется рекурсивной программой. При этом заметим, что
определяемые функциональные символы не интерпретируются.
Протокол выполнения программы (RS1, I1), где I1 интерпретация из практического занятия 1 (Рис. 1.1), выглядят
следующим образом:
№ п/п
1
2
Значение терма для (RS1, I1)
F(4)
4*F(3)
18
3
4
5
6
4*(3*F(2))
4*(3*(2*F(1)))
4*(3*(2*(1*F(0))))
4*(3*(2*(1*1)))=24
8. Номер варианта
0
1
10
5
Последняя цифра зачетной книжки
2
3
4
5
6
7
Номер варианта
4
2
6
3
1
9
8
9
7
8
9. Варианты заданий
Номер
варианта
Действия, выполняемые программой
1
Расчет суммы членов арифметической
прогрессии. Разность арифметической
прогрессии d=1
2
Расчет произведения первых членов
арифметической
прогрессии.
Знаменатель прогрессии d=1
3
Расчет чисел Фибоначчи
4
Вкладчик положил в банк сумму в sum
единиц под p процентов за один период
времени (год). Составить рекурсивную
программу-функцию,
возвращающую
величину вклада по истечении n
периодов времени (n = 1, 2, …).
5
Пусть a - вещественное число отличное
от нуля и n есть целое неотрицательное
число.
Составить
рекурсивную
программу-функцию,
возвращающую
19
Пример для
выполнения
программы
Расчет суммы
первых
пяти
членов
прогрессии
Расчет
произведения
первых
пяти
членов
прогрессии
Расчет
седьмого числа
Фибоначчи
Рассчитать
величину
вклада в 100
руб. через 10
лет при
процентной
ставке в 2%.
Найти
значение 4 3
величину a n
6
7
8
Составить рекурсивную программуфункцию подсчета количества всех
положительных делителей натурального
числа n.
Нахождение наибольшего общего
делителя (алгоритм Евклида)
Рассчитать
количество
делителей для
числа 10.
Найти
наибольший
общий
делитель
чисел: 45 и 72
Составить рекурсивную программу- Рассчитать
функцию вычисления биномиальных значение
коэффициентов С(n,m), где n и m - целые функции C 3
3
и 0≤m≤n. При выполнении задачи
учитывать, что:
9
Расчет суммы первых n чисел Фибоначчи
10
Расчет произведения первых n чисел
Фибоначчи
20
Рассчитать
сумму пяти
первых чисел
Рассчитать
произведение
пяти первых
чисел
Практическое занятие №3
«Аксиоматическая семантика. Определение слабейших
предусловий операторов»
1. Цель занятия
Изучение аксиоматической семантики, преобразователей
предикатов и способов определения слабейших предусловий
операторов программ.
2. Литература
1.
В.Н. Агафонов. Спецификация программ: понятийные средства
и их организация. - Новосибирск: Наука (Сибирское отделение),
1987. - С. 30-73.
2.
Ian Sommerville. Software Engineering. - Addison-Wesley
Publishing Company, 1992. - P.
3.
Д. Скотт. Теория решеток, типы данных и семантика// Данные в
языках программирования. - М.: Мир, 1982. - С. 25-53.
4.
У. Дал, Э. Дейкстра, К. Хоор. Структурное программирование. М.: Мир, 1975. - С. 98-197.
3. Выполнение работы
 изучить аксиоматическую семантику, преобразователи предикатов
и
аксиоматическое
определение
операторов
языков
программирования;
 в соответствии с вариантом задания разработать алгоритм
программы, решающей поставленную задачу;
 составить стандартную схему программы и записать полученную
программу в линейной форме;
 для каждого оператора определить слабейшие предусловия;
 составить отчет по проделанной работе в соответствии с
требованиями, предъявляемыми в пункте 6 данного практического
занятия.
4. Контрольные вопросы
1. Что такое аксиоматическая семантика?
2. Что такое триада Хоара? Из чего она состоит?
3. Что такое слабейшие предусловия? Каким образом они
определяются?
4. Что такое преобразователь предикатов?
21
5. Перечислите свойства преобразователя предикатов.
6. Назовите слабейшие предусловия для основных операторов
программы..
7. Сформулируйте основную теорему инвариантности оператора
цикла.
5. Содержание работы
 ознакомиться с кратким теоретическим материалом, ответить на
контрольные вопросы;
 определить номер выполняемого варианта;
 для выполнения предложенного варианта необходимо разработать
алгоритм программы, решающей поставленную задачу;
 составить линейную форму стандартной схемы программ;
 на основе составленной линейной формы определить и записать
слабейшие предусловия для каждого оператора стандартной
схемы;
6. Содержание отчета
отчет должен содержать следующее:
 титульный лист с указанием наименования и цели занятия;
фамилии, имени, отчества и номера группы студента; фамилии,
имени, отчества преподавателя, а также номера выполняемого
варианта;
 дату выполнения работы;
 цель занятия;
 условия предложенной задачи;
 алгоритм
решения
поставленной
задачи
на
языке
программирования высокого уровня;
 линейную форму стандартную схемы программы;
 составленные слабейшие предусловия для каждого оператора
программы;
 выводы о проделанной работе.
7. Краткий теоретический материал
Аксиоматическая семантика
Аксиоматическая семантика была создана в процессе
разработки метода доказательства правильности программ. Данный
метод распространяет на программы область применения исчисления
22
предикатов. Семантику каждой синтаксической конструкции языка
можно определить как некий набор аксиом или правил вывода,
который можно использовать для вывода результатов выполнения
этой конструкции. Чтобы понять смысл всей программы (то есть
разобраться, что и как она делает), эти аксиомы и правила вывода
следует использовать так же, как при доказательстве обычных
математических теорем. В предположении, что значения входных
переменных удовлетворяют некоторым ограничениям, аксиомы и
правила вывода могут быть использованы для получения (вывода)
ограничений на значения других переменных после выполнения
каждого оператора программы. В конце концов, когда программа
выполнена, мы получаем доказательство того, что вычисленные
результаты удовлетворяют необходимым ограничениям на их
значения относительно входных значений. То есть, доказано, что
выходные данные представляют значения соответствующей функции,
вычисленной по значениям входных данных.
Такие доказательства показывают, что программа выполняет
вычисления, описанные ее спецификацией. В доказательстве каждый
оператор
программы
сопровождается
предшествующим
и
последующим логическими выражениями, устанавливающими
ограничения на переменные в программе. Эти выражения
используются для определения смысла оператора вместо полного
описания состояния абстрактной машины (как в операционной
семантике).
Аксиоматическая семантика основана на математической
логике. Будем называть предикат, помещенный в программу
утверждением. Утверждение, непосредственно предшествующее
оператору программы, описывает ограничения, наложенные на
переменные в данном месте программы. Утверждение, следующее
непосредственно за оператором программы, описывает новые
ограничения на те же (а возможно, и другие) переменные после
выполнения оператора.
Введем обозначение (триада Хоара)
{Q} S {R}
(3.1)
где Q, R - предикаты, S - программа (оператор или
последовательность операторов). Обозначение определяет следующий
смысл: «Если выполнение S началось в состоянии, удовлетворяющем
23
Q, то имеется гарантия, что оно завершится через конечное время в
состоянии, удовлетворяющем R».
Предикат Q называется предусловием или входным
утверждением S, предикат R - постусловием или выходным
утверждением. Следовательно, R определяет то, что нужно
установить. Можно сказать, что R определяет спецификацию задачи.
В предусловии Q нужно отражать тот факт, что входные переменные
получили начальные значения.
В дальнейшем при изучении утверждений мы будем
предполагать, что предусловия операторов вычисляются на основе
постусловий, хотя этот процесс можно рассматривать и с
противоположной точки зрения. Предположим, что.
Пример 3.1 Рассмотрим оператор присваивания для
целочисленных переменных и постусловие:
sum := 2 * х + 1 {sum > 1}
Одним из возможных предусловий данного оператора может
быть {х > 10}.
Слабейшими
предусловиями
называются
наименьшие
предусловия, обеспечивающие выполнение соответствующего
постусловия. Например, для приведенного выше оператора и его
постусловия предусловия {х > 10}, {х > 50} и {х > 1000} являются
правильными. Слабейшим из всех предусловий в данном случае будет
{х > 0}.
Преобразователь предикатов.
Э. Дейкстра рассматривает слабейшие предусловия, т.е.
предусловия, необходимые и достаточные для гарантии желаемого
результата.
«Условие, характеризующее множество всех начальных
состояний, при которых запуск обязательно приведет к событию
правильного завершения, причем система (машина, конструкция)
останется в конечном состоянии, удовлетворяющем заданному
постусловию,
называется
слабейшим
предусловием,
соответствующим этому постусловию».
Условие называют слабейшим, так как чем слабее условие, тем
больше состояний удовлетворяют ему. Наша цель - охарактеризовать
все возможные начальные состояния, которые приведут к желаемому
конечному состоянию.
24
Если S - некоторый оператор (последовательность операторов),
R - желаемое постусловие, то соответствующее слабейшее
предусловие будем обозначать wp(S, R).
Аббревиатура
wp
определяется
начальными
буквами
английских слов weakest (слабейший) и precondition (предусловие).
Предполагается, что известно, как работает оператор S (известна
семантика S), если можно вывести для любого постусловия R
соответствующее слабейшее предусловие wp(S, R).
Определение семантики оператора дается в виде правила,
описывающего, как для любого заданного постусловия R можно
вывести соответствующее слабейшее предусловие wp(S, R).
Для фиксированного оператора S такое правило, которое по
заданному предикату R вырабатывает предикат wp(S,R), называется
«преобразователем предикатов»: {wp(S, R)} S {R}.
Это значит, что описание семантики оператора S представимо с
помощью преобразователя предикатов. Применительно к конкретным
S и R часто бывает неважным точный вид wp(S,R), бывает достаточно
более сильного условия Q, т.е. условия, для которого можно доказать,
что утверждение Q => wp(S, R) справедливо для всех состояний.
Значит, множество состояний, для которых Q - истина, является
подмножеством того множества состояний, для которых wp(S, R) истина. Возможность работать с предусловиями Q, не являющимися
слабейшими, полезна, поскольку выводить wp(S, R) явно не всегда
практично.
Сформулируем свойства (по Э. Дейкстра) wp(S, R).
Свойство 1. wp (S, F) = F для любого S. (Закон исключенного
чуда).
Свойство 2. Закон монотонности. Для любого S и предикатов P
и R таких, что P => R для всех состояний, справедливо для всех
состояний wp(S, P) => wp(S, R).
Свойство 3. Дистрибутивность конъюнкции. Для любых S, P, R
справедливо
wp(S, P) AND wp(S, R) = wp(S, P AND R).
Свойство 4. Дистрибутивность дизъюнкции. Для любых S, P, R
справедливо
wp(S, P) OR wp(S, R) = wp(S, P OR R).
Если для каждого оператора языка по заданным постусловиям
можно вычислить слабейшее предусловие, то для программ на данном
языке может быть построено корректное доказательство.
25
Доказательство начинается с использования результатов, которые
надо получить при выполнении программы, в качестве постусловия
последнего оператора программы, и выполняется с помощью
отслеживания программы от конца к началу с последовательным
вычислением слабейших предусловий для каждого оператора. При
достижении начала программы первое ее предусловие отражает
условия, при которых программа вычислит требуемые результаты.
Для некоторых операторов программы вычисление слабейшего
предусловия на основе оператора и его постусловия является
достаточно простым и может быть задано с помощью аксиомы.
Однако, как правило, слабейшее предусловие вычисляется только с
помощью правила логического вывода, т.е. метода выведения
истинности одного утверждения на основе значений остальных
утверждений.
Аксиоматическое определение основных операторов
языка программирования в терминах wp.
Определим слабейшее предусловие для основных операторов:
оператора присваивания, составного оператора, оператора выбора и
оператора цикла.
Оператор присваивания имеет вид: x := E, где x - простая
переменная, E – выражение (типы x и E совпадают).
Определим слабейшее предусловие оператора присваивания как
Q = wp(x := E, R), где Q получается из R заменой каждого вхождения
x на E, что обозначим Q = RxЕ.
Предполагается, что значение Е определено и вычисление
выражения Е не может изменить значения ни одной переменной.
Последнее ограничение запрещает функции с побочным эффектом.
Следовательно, можно использовать обычные свойства выражений
такие, как ассоциативность, коммутативность и логические законы.
Составной оператор имеет вид: begin S1; S2; ... ; Sn end
Определим слабейшее предусловие для последовательности
двух операторов:
wp(S1;S2, R) = wp(S1, wp(S2, R)).
Аналогично слабейшее предусловие определяется для
последовательности из n операторов.
Оператор выбора определим так: if B1 → S1 П B2 → S2 ... П Bn
→ Sn fi
26
Здесь n  0, B1, B2, ..., Bn - логические выражения, называемые
охранами, S1, S2, ..., Sn - операторы, пара Bi → Si называется
охраняемой командой, П - разделитель, if и fi играют роль
операторных скобок.
Выполняется оператор следующим образом.
Проверяются все Bi. Если одна из охран не определена, то
происходит аварийное завершение. Далее, по крайней мере, одна из
охран должна иметь значение истина, иначе выполнение завершается
аварийно.
Выбирается одна из охраняемых команд Bi → Si, у которой
значение Bi истина, и выполняется Si.
Определим слабейшее предусловие:
wp(if, R) = BB AND (B1 => wp(S1, R)) AND ... AND (Bn =>
wp(Sn, R)),
где BB = B1 OR B2 OR ... OR Bn.
Предполагается, что охраны являются всюду определенными
функциями (значение их определено во всех состояниях).
Естественно определить wp(if, R) с помощью кванторов:
wp(if, R) = ( i: 1  i  n : Bi ) AND (i: 1  i  n : Bi => wp(Si, R))
Пример 2. Определить z = |x|.
С использованием оператора выбора :if x  0 → z := x П x  0 →
z := -x fi.
К особенностям оператора выбора следует отнести, во-первых,
тот факт, что он включает условный оператор (if... then..),
альтернативный оператор (if… then... else...) и оператор выбора (case).
Во-вторых, оператор выбора не допускает умолчаний, что
помогает при разработке сложных программ, так как каждая
альтернатива представлена подробно, и возможность что-либо
упустить уменьшается.
В-третьих, благодаря отсутствию умолчаний, запись оператора
выбора представлена в симметричном виде.
Оператор цикла. В обозначениях Э. Дейкстры цикл имеет вид:
do B → S do.
Обозначим это соотношение через DO и представим его в
следующем виде:
DO: do B1 → S1 П B2 → S2 ... П Bn → Sn od, где n  0, Bi → Si
- охраняемые команды.
Выполняется оператор следующим образом. Пока возможно
выбирается охрана Bi со значением истина, и выполняется
27
соответствующий оператор Si. Как только все охраны будут иметь
значение ложь, выполнение DO завершится.
Выбор охраны со значением истина и выполнение
соответствующего оператора называется выполнением шага цикла.
Если истинными являются несколько охран, то выбирается любая из
них.
Следовательно, оператор DO эквивалентен оператору
do BB → if B2 → S1 П B2 → S2 ... П Bn → Sn fi od или do BB →
IF od,
где BB - дизъюнкция охран, IF - оператор выбора.
Дадим формальное определение слабейшего предусловия для
оператора цикла DO.
Пусть предикат H0(R) определяет множество состояний, в
которых выполнение DO завершается за 0 шагов (в этом случае все
охраны с самого начала ложны, после завершения R имеет значение
истина):
H0(R) = NOT BB AND R
Другими словами, требуется, чтобы оператор цикла DO
завершил работу, не производя выборки охраняемой команды, что
гарантируется первым конъюнктивным членом предиката H0(R): NOT
BB = T. При этом истинность R до выполнения DO является
необходимым условием для истинности R после выполнения DO.
Определим предикат Hk(R) как множество состояний, в которых
выполнение DO заканчивается за k шагов при значении R истина
(Hk(R) будет определяться через Hk-1(R)):
Hk(R) = H0(R) OR wp(IF, Hk-1(R)), k > 0 → wp(DO, R) = ( k: k 
0: Hk(R)).
Это значит, что должно существовать такое значение k, что
потребуется не более, чем k шагов, для обеспечения завершения
работы в конечном состоянии, удовлетворяющем постусловию R.
Определение DO. Если предикаты Hk(R) задаются в виде
Hk(R) = NOT B AND R, k = 0
Hk(R) = wp(IF, Hk-1(R)), k > 0, → wp (DO,R)=( k: k  0: Hk(R))
Основная теорема для оператора цикла. Пусть оператор
выбора IF и предикат P таковы, что для всех состояний справедливо
(P AND BB) => wp(IF, R).
(3.2)
Тогда для оператора цикла справедливо:
(P AND wp(DO, T)) => wp(DO, P AND NOT BB).
28
Эта теорема известна как основная теорема инвариантности для
цикла. Предикат Р, истинный перед выполнением и после выполнения
каждого шага цикла, называется инвариантным отношением или
просто инвариантом цикла. В математике термин «инвариантный»
означает не изменяющийся под воздействием совокупности
рассматриваемых математических операций.
Поясним смысл теоремы. Условие (3.2) означает, что если
предикат P первоначально истинен и одна из охраняемых команд
выбирается для выполнения, то после ее выполнения P сохранит
значение истинности. После завершения оператора, когда ни одна из
охран не является истиной, будем иметь:
P AND NOT BB.
Работа завершится правильно, если условие wp(DO, T)
справедливо и до выполнения DO. Так как любое состояние
удовлетворяет T, то wp(DO,T) является слабейшим предусловием для
начального состояния такого, что запуск оператора цикла DO
приведет к правильно завершаемой работе.
29
8. Номер варианта
0
1
5
9
Последняя цифра зачетной книжки
3
4
5
6
7
Номер варианта
6
3
2
7
4
10
2
8
9
8
1
9. Варианты заданий
Номер
варианта
1
2
3
4
5
6
7
8
9
10
Действия, выполняемые программой
Расчет суммы членов арифметической прогрессии.
Расчет суммы первых членов геометрической прогрессии.
Расчет чисел Фибоначчи
Расчет произведения членов арифметической прогрессии.
Расчет произведения первых членов геометрической
прогрессии.
Расчет суммы чисел Фибоначчи
Расчет произведения чисел Фибоначчи
Решение квадратного уравнения
Нахождение наименьшего общего кратного двух чисел
Нахождение наибольшего общего делителя (алгоритм
Евклида)
30
Практическое занятие №4
«Верификация программ»
1. Цель занятия
Изучение
верификации
как
способа
доказательства
правильности программ, метода индуктивных утверждений и правил
верификации Хоара.
2. Литература
1. Непомнящий В.А., Рякин О.М. Прикладные методы
верификации программ. М.: Радио и связь. 1988
2. Андерсон Р. Доказательство правильности программ. М.,
Мир, 1982.
3. Вирт Н. Систематическое программирование. Введение. М.,
Мир, 1977.
3. Выполнение работы
 изучить метода индуктивных утверждений и правила
верификации Хоара;
 в соответствии с вариантом задания разработать алгоритм
программы, решающей поставленную задачу;
 составить стандартную схему программы и записать полученную
программу в линейной форме;
 используя метод индуктивных утверждений и правила
верификации Хоара произвести верификацию программы;
 составить отчет по проделанной работе в соответствии с
требованиями, предъявляемыми в пункте 6 данного практического
занятия.
4. Контрольные вопросы
1. Какие методы доказательства правильности программ Вам
известны?
2. Что такое верификация программ?
3. В чем суть метода индуктивных утверждений?
4. Изложите алгоритм доказательства правильности программы
методом индуктивных утверждений.
5. Что такое набросок доказательства?
6. Сформулируйте правила верификации Хоара.
31
5. Содержание работы
 ознакомиться с кратким теоретическим материалом, ответить на
контрольные вопросы;
 определить номер выполняемого варианта;
 для выполнения предложенного варианта необходимо разработать
алгоритм программы, решающей поставленную задачу;
 составить линейную форму стандартной схемы программ;
 на основе составленной линейной формы составить входные и
выходные утверждения;
 построить и доказать условия верификации.
6. Содержание отчета
Отчет должен содержать следующее:
 титульный лист с указанием наименования и цели занятия;
фамилии, имени, отчества и номера группы студента; фамилии,
имени, отчества преподавателя, а также номера выполняемого
варианта;
 дату выполнения работы;
 цель занятия;
 условия предложенной задачи;
 алгоритм
решения
поставленной
задачи
на
языке
программирования высокого уровня;
 линейную форму стандартную схемы программы;
 составленные входное и выходное утверждения;
 построенные условия верификации;
 доказательство условий верификации;
 выводы о проделанной работе.
7. Краткий теоретический материал
Верификация программ.
Методы доказательства правильности программ.
Как известно, универсальные вычислительные машины могут
быть запрограммированы для решения самых разнородных задач - в
этом заключается одна из основных их особенностей, имеющая
огромную практическую ценность. Один и тот же компьютер, в
зависимости от того, какая программа находится у него в памяти,
32
способен осуществлять арифметические вычисления, доказывать
теоремы и редактировать тексты, управлять ходом эксперимента и
создавать проект автомобиля будущего, играть в шахматы и обучать
иностранному языку. Однако успешное решение всех этих и многих
других задач возможно лишь при том условии, что компьютерные
программы не содержат ошибок, которые способны привести к
неверным результатам.
Можно сказать, что требование отсутствия ошибок в
программном обеспечении совершенно естественно и не нуждается в
обосновании. Но как убедиться в том, что ошибки, в самом деле,
отсутствуют? Вопрос не так прост, как может показаться на первый
взгляд.
К неформальным методам доказательства правильности
программ относят отладку и тестирование, которые являются
необходимой
составляющей
на
всех
этапах
процесса
программирования, хотя и не решают полностью проблемы
правильности. Существенные ошибки легко найти, если использовать
соответствующие приемы отладки (контрольные распечатки,
трассировки).
Тестирование – процесс выполнения программы с намерением
найти ошибку, а не подтвердить правильность программы. Суть его
сводится к следующему. Подлежащую проверке программу
неоднократно запускают с теми входными данными, относительно
которых результат известен заранее. Затем сравнивают полученный
машиной результат с ожидаемым. Если во всех случаях тестирования
налицо совпадение этих результатов, появляется некоторая
уверенность в том, что и последующие вычисления не приведут к
ошибочному итогу, т.е. что исходная программа работает правильно.
Мы уже обсуждали понятие правильности программы с точки
зрения отсутствия в ней ошибок. С интуитивной точки зрения
программа будет правильной, если в результате ее выполнения будет
достигнут результат, с целью получения которого и была написана
программа. Сам по себе факт безаварийного завершения программы
еще ни о чем не говорит: вполне возможно, что программа в
действительности делает совсем не то, что было задумано. Ошибки
такого рода могут возникать по различным причинам.
В дальнейшем мы будем предполагать, что обсуждаемые
программы не содержат синтаксических ошибок, поэтому при
обосновании их правильности внимание будет обращаться только на
33
содержательную сторону дела, связанную с вопросом о том,
достигается ли при помощи данной программы данная конкретная
цель. Целью можно считать поиск решения поставленной задачи, а
программу рассматривать как способ ее решения. Программа будет
правильной, если она решит сформулированную задачу.
Метод установления правильности программ при помощи
строгих средств известен как верификация программ.
В отличие от тестирования программ, где анализируются
свойства отдельных процессов выполнения программы, верификация
имеет дело со свойствами программ.
В основе метода верификации лежит предположение о том, что
существует программная документация, соответствие которой
требуется доказать. Документация должна содержать:
 спецификацию ввода-вывода (описание данных, не зависящих от
процесса обработки);
 свойства отношений между элементами векторов состояний в
выбранных точках программы;
 спецификации и свойства структурных подкомпонентов
программы;
 спецификацию структур данных, зависящих от процесса
обработки.
К такому методу доказательства правильности программ
относится метод индуктивных утверждений, независимо
сформулированный К. Флойдом и П. Науром.
Суть этого метода состоит в следующем:
1) формулируются входное и выходное утверждения: входное
утверждение описывает все необходимые входные условия для
программы (или программного фрагмента), выходное утверждение
описывает ожидаемый результат;
2) предполагая истинным входное утверждение, строится
промежуточное утверждение, которое выводится на основании
семантики операторов, расположенных между входом и выходом
(входным и выходным утверждениями); такое утверждение
называется выведенным утверждением;
3) формулируется теорема (условия верификации):
из выведенного утверждения следует выходное утверждение;
4) доказывается теорема; доказательство свидетельствует о
правильности программы (программного фрагмента).
34
Доказательство проводится при помощи хорошо разработанных
математических методов, использующих исчисление предикатов
первого порядка.
Условия верификации можно построить и в обратном
направлении, т.е., считая истинным выходное утверждение, получить
входное утверждение и доказывать теорему: «из входного
утверждения следует выведенное утверждение».
Такой метод построения условий верификации моделирует
выполнение программы в обратном направлении. Другими словами,
условия верификации должны отвечать на такой вопрос: если
некоторое утверждение истинно после выполнения оператора
программы, то, какое утверждение должно быть истинным перед
оператором?
Построение индуктивных утверждений помогает формализовать
интуитивные представления о логике программы. Оно и является
самым сложным в процессе доказательства правильности программы.
Это объясняется, во-первых, тем, что необходимо описать все
содержательные условия, и, во-вторых, тем, что необходимо
аксиоматическое описание семантики языка программирования.
Важным шагом в процессе доказательства является
доказательство завершения выполнения программы, для чего бывает
достаточно неформальных рассуждений.
Таким образом, алгоритм доказательства правильности
программы методом индуктивных утверждений представляется в
следующем виде:
1) Построить структуру программы.
2) Выписать входное и выходное утверждения.
3) Сформулировать для всех циклов индуктивные утверждения.
4) Составить список выделенных путей.
5) Построить условия верификации.
6) Доказать условие верификации.
7) Доказать, что выполнение программы закончится.
Этот метод сравним с обычным процессом чтения текста
программы (метод сквозного контроля). Различие заключается в
степени формализации.
Преимущество верификации состоит в том, что процесс
доказательства настолько формализуем, что он может выполняться на
вычислительной машине. В этом направлении в восьмидесятые годы
35
проводились исследования, даже создавались автоматизированные
диалоговые системы, но они не нашли практического применения.
Использование утверждений в программах.
Утверждения используются для доказательства правильности
программ. Тогда утверждения необходимо формулировать в
некоторой формальной логической системе. Обычно используется
исчисление предикатов первого порядка.
Исчисление - это метод или процесс рассуждений посредством
вычислений над символами. В исчислении предикатов утверждения
являются логическими переменными или выражениями, имеющими
значение T - истина или F - ложь. Наша цель - при написании
программы некоторым способом доказать истинность утверждения триады Хоара {Q} S {R}. Для этого нужно уметь записывать его в
исчислении предикатов и формально доказывать его истинность.
Предикат, помещенный в программу, был нами назван
утверждением. Утверждается, что он истинен в соответствующий
момент выполнения программы. В предусловии Q нужно отражать тот
факт, что входные переменные получили начальные значения. Для
обозначения начальных значений будем использовать большие буквы.
Пример 4.1 Пусть надо определить приближенное значение
квадратного корня: s = sqrt(n), где
n, s  Nat. Определим
постусловие в виде:
R: s*s  n < (s+1)*(s+1).
Пример 4.2 Даны целочисленные n > 0 и массив a[1,...,n].
Отсортировать массив, т.е. установить
R: ( i: 1  i < n: a[i]  a[i+1]).
Пример 4.3 Определить x как максимальное значение массива
a[1,...,n]. Определим постусловие:
R: {x = max({y | y  a})}.
Для построения программы следует определить математическое
понятие max. Тогда
R: {( i: 1  i  n: x = a[i]) AND ( i: 1  i  n: a[i] = x)}.
Пример 4.4 Пусть имеем программу S обмена значениями двух
целых переменных a и b. Сформулируем входное и выходное
утверждения программы и представим программу S в виде предиката:
{ a = A AND b = B } S { a = B AND b = A },
(4.1)
где A, B - конкретные значения переменных a, b.
36
Программа вместе с утверждениями между каждой парой
соседних операторов называется наброском доказательства.
Последовательно, для каждого оператора программы формулируя
предикат (1), можно доказать, что программа удовлетворяет своим
спецификациям. Представим набросок доказательства для программы
S:
{ a = A AND b = B }
r := a; { r = a AND a = A AND b = B };
a := b; { r = a AND a = B AND b = B };
b := r; { a = B AND b = A }.
Не обязательно набросок доказательства должен быть настолько
полным. Для документирования программы нужно вставить
достаточно утверждений, чтобы программа стала понимаемой.
Программа, содержащая утверждения для ее документирования,
называется аннотированной программой. Чтобы использовать
утверждения для доказательства
правильности программы,
необходимы соответствующие правила верификации.
Правила верификации Хоара.
Сформулируем
правила
(аксиомы)
К.Хоара,
которые
определяют
предусловия
как
достаточные
предусловия,
гарантирующие, что исполнение соответствующего оператора при
успешном завершении приведет к желаемым постусловиям.
A1. Аксиома присваивания: { Ro } x := Е { R }
Неформальное объяснение аксиомы: так как x после
выполнения будет содержать значение Е, то R будет истинно после
выполнения, если результат подстановки Е вместо x в R истинен
перед выполнением. Таким образом, Ro = R(x) при x = E. Для Ro
вводится обозначение: Ro = RxЕ (у Вирта) или Rx→Е (у Дейкстры),
что означает, что x заменяется на Е.
Аксиома присваивания будет иметь вид:{RxЕ} x := Е {R}.
Сформулируем два очевидных правила монотонности.
A2. Если известно: { Q } S { P } и { P } => { R }, то { Q } S { R }
A3. Если известно: { Q } S { P } и { R } => { Q }, то { R } S { P }
Пусть S - это последовательность из двух операторов S1; S2
(составной оператор).
A4. Если известно:{ Q } S1 { P1 } и { P1 } S2 { R }, то { Q } S {
R }.
37
Это правило можно сформулировать для последовательности,
состоящей из n операторов.
Сформулируем правило для условного оператора (краткая
форма).
A5. Если известно:
{ Q AND B } S1 { R } и { Q NOT B } => { R },то { Q } if B then
S1 { R }.
Правило A5 соответствует интерпретации условного оператора
в языке программирования.
Сформулируем правило для альтернативного оператора (полная
форма условного оператора).
A6. Если известно: { Q AND B } S1 { R } и { Q NOT B } S2 { R
},то { Q } if B then S1 else S2 { R }.
Сформулируем правила для операторов цикла.
Предусловия и постусловия цикла until удовлетворяют правилу:
A7. Если известно: { Q AND NOT B } S1 { Q }, то { Q } repeat S1
until B { Q AND NOT B }
Правило отражает инвариантность цикла. В данном случае
единственная операция - это выполнение шага цикла при условии
истинности Q вначале.
Предусловия и постусловия цикла while удовлетворяют
правилу:
A8. Если известно: { Q AND B } S1 { Q } , то { Q } while B do S1
{ Q AND NOT B }
Правила A1 - A8 можно использовать для проверки
согласованности передачи данных от оператора к оператору, для
анализа структурных свойств текстов программ, для установления
условий окончания цикла и для анализа результатов выполнения
программы.
Пример 4.5 (верификация программы) Пусть надо
определить частное q и остаток r от деления x на y.
Входные данные x, y и выходные данные q, r  Nat, причем y > 0.
Задать(x,y); /* x,y получают конкретные значения X,Y */
r := x; q := 0;
while y  r do
begin
r := r - y; q := q + 1
end;
выдать(q,r);
38
Сформулируем постусловие
R: (r < y) AND (x = y*q + r)
Нужно доказать, что
{y > 0 AND x/y} S {(r < y) AND (x = y*q + r )}.
Доказательство.
Очевидно, что Q => x = x + y * 0.
Применим аксиому A1 к оператору r := x, тогда получим { x = x + y *
0 } r := x { x = r + y * 0 }
Аналогично, применяя A1 к оператору q := 0, получим: { x = r + y * 0 }
q := 0 { x = r + y*q }
Применяя правило A3 к результатам пунктов 1 и 2, получим { Q } r :=
x{x=r+y*0}
Применяя правило A4 к результатам пунктов 4 и 3, получим { Q } r :=
x; q := 0 { x = r + y*q }
Выполним равносильное преобразование x = r + y * q AND y  r => x =
(r - y) + y*(q + 1)
Применяя правило A1 к оператору r:= r - y, получим {x = (r - y) + y*( q
+ 1)} r:= r - y {x = r+ y*(q+1)}
Для оператора q := q + 1 аналогично получим { x = r + y*(q + 1) } q :=
q + 1 { x = r + y*q }
Применяя правило A4 к результатам пунктов 7 и 8, получим
{ x = (r - y) + y*( q + 1) } r := r - y; q := q + 1 { x = r + y*q }
Применяя правило A2 к результатам пунктов 6 и 9, получим
{ x = r + y*q AND y  r } r := r - y; q := q + 1 { x = r + y*q }
Применяя правило A8 к результату пункта 10, получим
{x = r + y*q } while y  r do begin r := r - y; q := q + 1 end { NOT (y <= r)
AND (x = r + y*q) }
Утверждение x = r + y*q является инвариантом цикла, так как
значение его остается истинным до цикла и после выполнения
каждого шага цикла.
Применяя правило A4 к результатам пунктов 5 и 11, получаем то, что
требовалось доказать,
{ Q } S { NOT (y  r) AND (x = r + y*q) }
Осталось доказать, что выполнение программы заканчивается.
Доказывать будем от противного, т.е. предположим, что программа не
заканчивается.
Тогда
должна
существовать
бесконечная
последовательность значений r и q, удовлетворяющая условиям
1) y  r;
2) r, q  Nat.
39
Но значение r на каждом шаге цикла уменьшается на
положительную величину: r := r - y (y > 0). Значит,
последовательность значений r и q является конечной.
8. Номер варианта
0
1
4
1
Последняя цифра зачетной книжки
3
4
5
6
7
Номер варианта
5
9
6
3
8
7
2
8
9
10
2
9. Варианты заданий
Номер
варианта
1
2
3
4
5
6
7
8
9
10
Действия, выполняемые программой
Расчет суммы членов арифметической прогрессии.
Расчет суммы первых членов геометрической прогрессии.
Расчет чисел Фибоначчи
Расчет произведения членов арифметической прогрессии.
Расчет произведения первых членов геометрической
прогрессии.
Расчет суммы чисел Фибоначчи
Расчет произведения чисел Фибоначчи
Решение квадратного уравнения
Нахождение наименьшего общего кратного двух чисел
Нахождение наибольшего общего делителя (алгоритм
Евклида)
40
Практическое занятие №5
«Моделирование систем на основе сетей Петри»
1. Цель занятия
Изучение сетей Петри. Моделирование систем на основе сетей
Петри.
2. Литература
 Котов B.E. Сети Петри. М., Наука, 1984.
 Питерсон Дж. Теория сетей Петри и моделирование систем. - М.:
Мир, 1984.
 Майника Э. Алгоритмы оптимизации на сетях и графах /Под ред.
Е.К.Масловского - М.: Мир,1981. - 322 c.
3. Выполнение работы
 Изучить:
 структуру и состав сетей Петри;
 маркировку сетей Петри;
 правила выполнения сетей Петри;
 способы моделирования процессов в сетях Петри
 составить алгоритм выполняемого процесса;
 определить множества условий и событий для процесса;
 построить сеть Петри для моделируемого процесса;
 описать работу полученной сети Петри;
 составить отчет по проделанной работе в соответствии с
требованиями, предъявляемыми в пункте 6 данного практического
занятия.
4.
1.
2.
3.
4.
5.
6.
7.
8.
Контрольные вопросы
Дайте определение сети Петри.
Чем определяется структура сети Петри?
Что такое граф сети Петри? Как он строится?
Что такое маркировка сети Петри?
Сформулируйте правила выполнения сетей Петри?
Что такое событие в сетях Петри?
Что такое условие в сетях Петри?
Кратко сформулируйте алгоритм моделирования процессов в
сетях Петри
41
5. Содержание работы
 Ознакомиться с кратким теоретическим материалом, ответить на
контрольные вопросы;
 определить номер выполняемого варианта;
 для заданного варианта построить составить алгоритм
выполняемого процесса;
 определить множества условий и событий для процесса;
 построить сеть Петри для моделируемого процесса;
 описать работу полученной сети Петри.
6. Содержание отчета
Отчет должен содержать следующее:
 титульный лист с указанием наименования и цели занятия;
фамилии, имени, отчества и номера группы студента; фамилии,
имени, отчества преподавателя, а также номер выполняемого
варианта;
 дату выполнения работы;
 цель занятия;
 условия предложенной задачи;
 алгоритм моделируемого процесса;
 перечень событий и условий моделируемого процесса;
 таблицу пред- и постусловий для событий и условий
моделируемого процесса;
 описать работу полученной сети Петри;
 выводы о проделанной работе.
7. Краткий теоретический материал
7.1. Введение в сети Петри
Сети Петри это инструмент для математического
моделирования и исследования сложных систем. Цель представления
системы в виде сети Петри и последующего анализа этой сети состоит
в получении важной информации о структуре и динамическом
поведении моделируемой системы. Эта информация может
использоваться для оценки моделируемой системы и выработки
предложений по ее усовершенствованию. Впервые сети Петри
предложил немецкий математик Карл Адам Петри.
42
Сети Петри предназначены для моделирования систем, которые
состоят из множества взаимодействующих друг с другом компонент.
При этом компонента сама может быть системой. Действиям
различных компонент системы присущ параллелизм. Примерами
таких систем могут служить вычислительные системы, в том числе и
параллельные,
компьютерные
сети, программные
системы,
обеспечивающие их функционирование, а также экономические
системы, системы управления дорожным движением, химические
системы, и т. д.
В одном из подходов к проектированию и анализу систем сети
Петри используются, как вспомогательный инструмент анализа. Здесь
для построения системы используются общепринятые методы
проектирования. Затем построенная система моделируется сетью
Петри, и модель анализируется. Если в ходе анализа в проекте
найдены изъяны, то с целью их устранения проект модифицируется.
Модифицированный проект затем снова моделируется и
анализируется. Этот цикл повторяется до тех пор, пока проводимый
анализ не приведет к успеху.
Другой подход предполагает построение проекта сразу в виде
сети Петри. Методы анализа применяются только для создания
проекта, не содержащего ошибок. Затем сеть Петри преобразуется в
реальную рабочую систему.
В
первом
случае
необходима
разработка
методов
моделирования систем сетями Петри, а во втором случае должны быть
разработаны методы реализации сетей Петри системами.
7.2. Основные определения
7.2.1. Теоретико-множественное определение сетей
Петри
Пусть мультимножество это множество, допускающее
вхождение нескольких экземпляров одного и того же элемента.
Сеть Петри N является четверкой N=(P,Т,I,O), где
P = {p1, p2,..., pn} — конечное множество позиций, n  0;
T = {t1, t2,..., tm} — конечное множество переходов, m  0;
I: T  P* — входная функция, сопоставляющая переходу
мультимножество его входных позиций;
О: T  P* - выходная функция, сопоставляющая переходу
мультимножество его выходных позиций.
43
Позиция pP называется входом для перехода tT, если pI(t).
Позиция pP называется выходом для перехода tT, если pO(t).
Структура сети Петри определяется ее позициями, переходами,
входной и выходной функциями.
Пример 5.1 Сеть Петри N =(P,T,I,O),
P={p1, p2, p3},
T={t1, t2},
I(t1)={ p1, p1, p2},
O(t1)={p3},
I(t2)={ p1, p2, p2},
O(t2)={p3}.
Рис. 5.1
Использование мультимножеств входных и выходных позиций
перехода, а не множеств, позволяет позиции быть кратным входом и
кратным выходом перехода соответственно. При этом кратность
определяется числом экземпляров позиции в соответствующем
мультимножестве.
7.2.2. Графы сетей Петри.
Наиболее наглядным представлением сети Петри является её
графическое представление, которое представляет собой двудольный,
ориентированный мультиграф.
Граф сети Петри обладает двумя типами узлов: кружок ,
представляющий позицию сети Петри; и планка , представляющая
переход сети Петри. Ориентированные дуги этого графа (стрелки)
соединяют переход с его входными и выходными позициями. При
этом дуги направлены от входных позиций к переходу и от перехода к
выходным позициям. Кратным входным и выходным позициям
перехода соответствуют кратные входные и выходные дуги. Граф сети
Петри примера 5.1.
44
В графе сети Петри не возможны дуги между двумя позициями
и между двумя переходами.
7.2.3. Маркировка сетей Петри.
Маркировка — это размещение по позициям сети Петри фишек,
изображаемых на графе сети Петри точками. Фишки используются
для определения выполнения сети Петри. Количество фишек в
позиции при выполнении сети Петри может изменяться от 0 до
бесконечности.
Маркировка  сети Петри N=(P,T,I,О) есть функция,
отображающая множество позиций P во множество Nat
неотрицательных целых чисел. Маркировка , может быть также
определена как n-вектор =<

(pn)>, где n –
1
2),
число позиций в сети Петри и для каждого 1  i 
(pi)  Nat –
количество фишек в позиции pi.
Маркированная сеть Петри N=(P,Т,I,О,) определяется
совокупностью структуры сети Петри (P,T,I,О) и маркировки .
Рис. 5.2
На рисунке 5.2 представлена маркированная сеть Петри  =
<1,0,1>.
Множество всех маркировок сети Петри бесконечно. Если
фишек, помещаемых в позицию слишком много, то удобнее не
рисовать фишки в кружке этой позиции, а указывать их количество.
7.2.4. Правила выполнения сетей Петри.
Сеть Петри выполняется посредством запусков переходов.
Запуск перехода управляется фишками в его входных позициях и
сопровождается удалением фишек из этих позиций и добавлением
новых фишек в его выходные позиции.
Переход может запускаться только в том случае, когда он
разрешен. Переход называется разрешенным, если каждая из его
45
входных позиций содержит число фишек, не меньшее, чем число дуг,
ведущих из этой позиции в переход (или кратности входной дуги).
Пусть функция ^#: PT  Nat для произвольных позиции pP и
перехода tТ задает значение ^#(p,t), которое совпадает с кратностью
дуги, ведущей из p в t, если такая дуга существует, и с нулем, в
противном случае.
Пусть функция #^: TP Nat для произвольных и перехода tT
позиции pP задает значение #^(t,p), которое совпадает с кратностью
дуги, ведущей из t в p, если такая дуга существует, и с нулем, в
противном случае.
Переход tT в маркированной сети Петри N=(P,T,1,О,)
разрешен, если для всех p  I(t) справедливо 
 ^#(p,t).
Запуск разрешённого перехода tT из своей входной позиции
pI(t) удаляет ^#(p,t) фишек, а в свою выходную позицию p’ O(t)
добавляет #^(t,p’) фишек.
а
б
Рис. 5.3
Сеть Петри до запуска перехода t1 (рис. 5.3, а). Сеть Петри
после запуска перехода t1 (рис. 5.3, б).
Переход t в маркированной сети Петри с маркировкой  может
быть запущен всякий раз, когда он разрешен и в результате этого
запуска образуется новая маркировка ', определяемая для всех pP
следующим соотношением:
'(p)= (p) – ^#(p,t) + #^(t,p).
Запуски могут осуществляться до тех пор, пока существует хотя
бы один разрешенный переход. Когда не останется ни одного
разрешенного перехода, выполнение прекращается.
Если запуск произвольного перехода t преобразует маркировку
 сети Петри в новую маркировку ', то будем говорить, что '
46
достижима из  посредством запуска перехода t и обозначать этот
факт, как  t '. Это понятие очевидным образом обобщается для
случая последовательности запусков разрешённых переходов. Через
R(N,) обозначим множество всех достижимых маркировок из
начальной маркировки  в сети Петри N.
Преобразование маркировки сети Петри изображено на рисунке
5.3. Переход t1
 =<5,1> в маркировку
’=<2,3>.
7.3. Моделирование систем на основе сетей Петри
7.3.1. События и условия
Представление системы сетью Петри основано на двух
основополагающих понятиях: событиях и условиях. Возникновением
событий управляет состояние системы, которое может быть описано
множеством условий. Условие может принимать либо значение
«истина», либо значение «ложь».
Возникновение события в системе возможно, если выполняются
определённые условия – предусловия события. Возникновение
события может привести к выполнению других условий –
постусловий события. В качестве примера рассмотрим следующую
ниже задачу моделирования.
Пример 5.2. Моделирование последовательной обработки
запросов сервером базы данных. Сервер находится в состоянии
ожидания до тех пор, пока от пользователя не поступит запрос
клиента, который он обрабатывает и отправляет результат такой
обработки пользователю.
Условиями для рассматриваемой системы являются:
а) сервер ждет;
б) запрос поступил и ждет;
в) сервер обрабатывает запрос;
г) запрос обработан.
Событиями для этой системы являются:
1.Запрос поступил.
2. Сервер начинает обработку запроса.
3. Сервер заканчивает обработку запроса.
4. Результат обработки отправляется клиенту.
Для перечисленных событий можно составить следующую
таблицу их пред- и постусловий
47
Событие
Предусловия
Постусловия
1
нет
б
2
а, б
в
3
в
г, а
4
г
нет
Такое представление системы легко моделировать сетью Петри.
В сети Петри условия моделируются позициями, события —
переходами. При этом входы перехода являются предусловиями
соответствующего
события;
выходы
—
постусловиями.
Возникновение события моделируется запуском соответствующего
перехода. Выполнение условия представляется фишкой в позиции,
Рис. 5.4
соответствующей этому условию. Запуск перехода удаляет фишки,
представляющие выполнение предусловий и образует новые фишки,
которые представляют выполнение постусловий.
На рисунке 5.4. предусловие выполняется для события 2.
7.3.2. Одновременность и конфликт
Особенность сетей Петри - их асинхронная природа. В сетях
Петри отсутствует измерение времени. В них учитывается лишь
важнейшее свойство времени – частичное упорядочение событий.
Выполнение сети Петри (или поведение моделируемой
системы) рассматривается здесь как последовательность дискретных
событий, которая является одной из возможных. Если в какой-то
момент времени разрешено более одного перехода, то любой из них
может стать «следующим» запускаемым. Переходы в сети Петри,
моделирующей некоторую систему, представляют ее примитивные
события (длительность которых считается равной 0), и в один момент
времени может быть запущен только один разрешённый переход.
Моделирование
одновременного
(параллельного)
возникновения независимых событий системы в сети Петри
48
а
б
Рис. 5.5
демонстрируется на рисунке слева (рис. 5.5, а).
В этой ситуации два перехода являются разрешенными и не
влияют друг на друга в том смысле, что могут быть запущены один
вслед за другим в любом порядке.
Другая ситуация в приведенной справа (рис. 5.5, б) сети Петри. Эти
два разрешённые перехода находятся в конфликте, т. е. запуск одного
из них удаляет фишку из общей входной позиции и тем самым
запрещает запуск другого. Таким образом, моделируются
взаимоисключающие события системы
8. Номер варианта
0
1
3
8
Последняя цифра зачетной книжки
2
3
4
5
6
7
Номер варианта
2
9
7
10
6
4
8
9
1
5
9. Варианты заданий
Номер
Моделируемый процесс
варианта
1
Работа автомата разменивающего монеты
2
Работа автомата продающего прохладительные напитки
3
Установление местного телефонного соединения между
двумя абонентами
4
Работа критической секции на примере трех
взаимодействующих процессов
5
Работа объекта синхронизации ОС Windows ожидающий
таймер
на
примере
трех
одновременно
взаимодействующих процессов
6
Работа банкомата
7
Установление междугороднего телефонного соединения с
49
8
9
10
возможностью отказа в обслуживании
Работа объекта синхронизации ОС Windows событие на
примере
трех
одновременно
взаимодействующих
процессов
Работа Интернет магазина
Работа объекта синхронизации семафор на примере трех
одновременно взаимодействующих процессов
50
51
52
Download