Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Теория вычислительных процессов и структур. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
позиции, она сигнализирует о том, что счетчик команд установлен на готовность выполнения следующей инструкции.
На рис. 5.20 представлена сеть Петри для процесса вычисления квадратного уравнения. При построении использованы условные обо­значения табл. 5.1.
Рис. 5.20. Сеть Петри, моделирующая процесс решения
квадратного уравнения
Каждая позиция имеет единственный выходной переход, кроме позиции, предшествующей принятию решения, у которой имеется два выходных перехода, соответствующих истинному и ложному значе­нию проверяемого условия.
Переходы, моделирующие вычисления, имеют один вход и один выход и не могут находиться в конфликте. Действие же, связан­ное с принятием решения, напротив, создает в сети конфликт. Выбор способа разрешения конфликта, как мы уже говорили ранее, не регла­ментируется формализмом сети: он либо недетерминирован, либо управляется извне.
Рассмотрим еще один пример построения сети Петри.
Пусть дана программа, которая выводит на экран квадраты на­туральных чисел от 1 до некоторого заданного n. Пользователь вводит
61
значение переменной n, а переменной i, являющейся счетчиком итера­ций цикла, присваивается значение 1. Далее запускается цикл. Его тело состоит из вычисления значения переменной x, которой при­сваивается значение i2 для каждой итерации, вывода x на экран и увели­чения i на 1. Тело цикла выполняется, пока значение i не превышает n.
Текст описанной программы представлен ниже:
begin readln(n); i:=1; while (i<=n) do begin
x:=i*i;
writeln(x);
i:=i+1; end; end.
Соответствующая сеть Петри представлена на рис. 5.21. В дан­ной модели использован несколько иной подход по сравнению с сетью на рис. 5.20. Поясним использованную здесь интерпретацию позиций и переходов.
Рис. 5.21. Сеть Петри, моделирующая работу алгоритма программы
вывода на экран квадратов натуральных чисел
62
Позиции p1 и p2 указывают на необходимость ввода исходных данных, а именно – ввод значения переменной n и присваивание на­чального значения i соответственно. Срабатывание перехода t1 означа­ет, что все исходные данные поступили, и можно запускать процесс вычислений.
Позиция p3 моделирует конфликт при проверке логического условия выполнения тела цикла. Если условие выполнено, срабатыва­ет переход t2, который моделирует выполнение тела цикла. После это­го фишка вновь возвращается в позицию p3, и проверка производится уже на следующей итерации. Если i приняло значение, большее n, вы­полнение цикла (а вместе с ним – и программы) завершается, что со­ответствует срабатыванию перехода t3 и переводу единственной фиш­ки сети в позицию p4, которая уже не дает возможности для срабаты­вания каких-либо переходов.
Отметим, что событие, моделируемое переходом t2, можно считать непримитивным и заменить его изображение прямоугольни­ком, иллюстрирующим наличие подсети. Данную подсеть, в свою оче­редь, можно привести в виде отдельной сети Петри, чтобы раскрыть сложный характер события.
63
6. СХЕМЫ ПРОГРАММ
Программа P
1
Программа P2
Схема программ
P1 и P
2
begin integer х, у, n; input(х, n); у:=1; L: y:=y*x; if y < n then goto L; print(y); end.
begin string х, у; integer n; input(х, n); у:=ε; L: y:=strncat(x, y); if len(y) < n then goto L; print(y); end.
begin input(х, n); у:=а; L: y:=f (x, y); if p(y, n) then goto L; print(y); end.
6.1. Базис класса стандартных схем программ
В предыдущем разделе в рамках изучения сетей Петри мы в качестве частного случая рассмотрели возможность моделирования процесса выполнения программы. В данном разделе мы целиком со­средоточимся на вопросах моделирования программ и рассмотрим специализированный инструмент для решения этой задачи – схемы программ.
Схема программы – это математическая модель, описывающая строение определенного класса программ. В данной модели конкрет­ные операции и функции заменены абстрактными символами из соот­ветствующих множеств.
Для того чтобы понять отличие программы от схемы програм­мы, рассмотрим пример в табл. 6.1.
Таблица 6.1
Сравнение двух программ и соответствующей им схемы
(во всех случаях вместо конкретного языка программирования
использован псевдокод)
Рассмотрим программу P1. Вначале выделяется память под три целочисленные переменные. Далее пользователю предлагается ввести значения для x и n, а y присваивается значение 1. После этого в стро­ке с меткой L значения y и x перемножаются, а результат присваи­вается y. Если полученное значение меньше n, то происходит возвра­щение к метке L, и указанные операции повторяются. Если y n, то на экран выводится его значение, и работа программы завершается. Та-
64
ким образом, программа P1 вычисляет степень переменной x до тех пор, пока она не превысит значение n.
В программе P2 вначале также выделяется память под пере­менные: две строковых и одну целочисленную. Далее пользователь вводит значения переменных x и n, а переменной y присваивается пустая строка . Далее в строке с меткой L переменной y присваивает­ся результат конкатенации x и y (конкатенация совершается посред­ством функции strncat). Если длина полученной в y строки не превы­шает n, производится повторение операций, происходящих после метки L. Как только длина строки y становится большей или рав­ной n, строка y выводится на экран, и программа завершает свою работу.
Нетрудно видеть, что, несмотря на то, что программы P1 и P2 выполняют абсолютно разные задачи и даже обрабатывают разные типы данных (программа P1 работает только с целочисленными пере­менными, а в программе P2 ключевую роль играют строковые), они имеют довольно ощутимое сходство. Сходство это заключается в их структуре. В обеих программах происходит следующее:
1) пользователю предлагается ввести значения двух перемен-
ных;
2) третьей переменной присваивается некоторая константа;
3) запускается цикл, условие выполнения которого зависит от логического выражения с двумя аргументами y и n, а тело сос­тоит из присваивания переменной y значения некоторой функции от x и y;
4) когда условие выполнения цикла становится ложным, про­исходит вывод на экран значения переменной y, и программа заверша­ет свою работу.
Описанная выше структура представлена в табл. 6.1 в третьем
столбце. В ней отсутствуют операторы выделения памяти под пере­менные, т.к. с точки зрения описания структуры и логики представ­ленных программ они не слишком существенны, и в схеме можно ог­раничиться начальным оператором.
Схемы программ, вообще говоря, строятся с применением оп-
ределенных символов, роль которых определяется принадлежностью к соответствующим множествам.
Полный базис В класса стандартных схем состоит из четырех
множеств символов, которые являются непересекающимися и счетны­ми. Из символов этих множеств строятся слова – операторы.
65
Множества символов полного базиса:
1. X = {х, x1, х2,..., у, y1, у2,.., z, z1, z2,..} – множество символов, называемых переменными.
2. F = {f
(0)
, f
(1)
, f
(2)
... g
(0)
, g
(1)
, g
(2)
,.., h
(0)
, h
(1)
(2)
, h
,..} – множество
функциональных символов. В верхнем индексе записывается мест­ность символа. Ближайший пример функционального символа –
обычная функция в программе. Местность представляет собой факти­чески количество аргументов, которое может принимать такая функ­ция. Символы с нулевой местностью – это, очевидно, константы. Их традиционно обозначают начальными буквами латинского алфавита, например: a, b, c.
Индексы местности можно опускать, если это не приводит к
двусмысленности или противоречиям.
3. Р = {р
(0)
, р
(1)
, р
(2)
,…, q
(0)
, q
(1)
(2)
, q
,...} – множество предикат-
ных символов. Предикат – это утверждение, истинность которого зави- сит от аргументов, входящих в него. Ближайший пример предикатного символа – это логическая функция в программе: в зависимости от зна­чений своих аргументов она возвращает значение либо «истина», либо «ложь». Предикатные символы так же, как и функциональные, обла­дают местностью. Нульместные предикатные символы представляют собой логические константы.
4. {start, stop, :=, (, ),…} – множество специальных сим­волов. Пример специального символа – оператор языка программиро­вания.
Здесь следует сделать оговорку относительно терминоло­гии. Под словом «символ» мы традиционно подразумеваем некото­рый единичный элементарный объект типа буквы, цифры, знака разделителя и т.п. Конструкции вида star или f (x, y) интуитивно не кажутся такими простыми элементами, что может вызывать недопонимание при изучении рассматриваемого материала. Следует просто привыкнуть к такому более широкому подходу к поня­тию символа, а также понятию слова, которое из таких символов стро­ится.
Введем еще два понятия, представляющих собой в некотором смысле обобщение для объектов, приведенных в определении мно­жеств базиса B.
Функциональное выражение, или терм, – это слово, постро­енное из переменных, функциональных и специальных симво-
66
лов. Термами являются односимвольные слова, состоящие из пере-
(2)
(n)
(1, 2,…, n), где 1,
(3)
(x, h
(y1, y2, y3)).
,…,
2
менных или констант, а также слова вида f n – термы.
Примеры термов: a, x, f
(1)
(x), g
Логическое выражение, или тест, – это слово вида
(n)
p
(1, 2,…, n), где p
(n)
– предикатный символ, а 1, 2,…, n – термы.
Логические константы также являются тестами.
Рассмотрим множество операторов. Оно включает в себя пять типов:
1. Начальный оператор – слово вида start(x1, х2,..., хk), где k > 0,
а x1, х2,..., хk – переменные, называемые результатами этого опе­ратора.
2. Заключительный оператор – слово вида stop(1, 2,…, n),
где n > 0, а 1, 2,…, n – термы. Переменные, входящие в термы
1, 2,…, n, называются аргументами этого оператора.
3. Оператор присваивания – слово вида х:=, где х – перемен-
ная (результат оператора), а – терм. Переменные, входящие в терм , называются аргументами этого оператора. Если – перемен­ная (х:=у), оператор присваивания называется пересылкой, а если
 – константа (x:=a), то – засылкой.
4. Условный оператор – логическое выражение. Входящие в
него переменные называются его аргументами.
5. Оператор петли – односимвольное слово loop.
Отметим, что, кроме полного базиса стандартных схем, воз­можны случаи как ограниченных базисов на его основе, когда из всего представленного многообразия берутся лишь отдельные элементы, так и случаи обогащенных схем, для которых базис расширяется новыми элементами, структурами данных и т.д. Мы сосредоточимся преиму­щественно на изучении описанного выше полного базиса стандартных схем программ.
Пример ограниченного базиса:
- множество переменных: X = {x1, x2, x3};
- множество функциональных символов: F = {a, f
- множество предикатных символов: P = {p
(1)
};
(1)
};
- множество специальных символов: {start, stop, , , (, ), :=}
(элементы выделены жирным шрифтом для лучшей читае­мости).
67
Соответственно, множество операторов (слов, которые можно построить из указанных символов) может быть следующим:
{start(x1, x2, x3), stop(x1, x2, x3), x1:=a, x2:=a, x3:=a, x1:=f (x1), x2:=f (x2), x3:=f (x3), p(x1), p(x2), p(x3)}.
6.2. Способы представления стандартной схемы программы
Как мы увидели из предыдущего раздела, схема программы описывает структурные особенности некоторого множества программ, не указывая семантику элементов этой структуры. Функции, предика­ты и переменные представлены абстракциями.
Удобно для изображения схемы программы использовать граф. Вершинами такого графа будут операторы из базиса B.
Сформулируем следующее определение: стандартная схема в базисе В есть конечный ориентированный граф без свободных дуг, обладающий вершинами следующих видов:
1. Начальная вершина. Соответствует начальному оператору и
единственна. Входящих дуг не имеет, выходящая только одна.
2. Заключительная вершина. Соответствует заключительному оператору. Таких вершин может быть несколько. Не имеет выходящих дуг.
3. Вершина-преобразователь. Соответствует оператору при­сваивания. Имеет только одну выходящую дугу.
4. Вершина-распознаватель. Соответствует условному опера­тору. Имеет две выходящих дуги, одна из которых помечается «0», а другая – «1» («условие не выполнено» и «условие выполнено» соот­ветственно).
5. Вершина-петля. Соответствует оператору петли. Не имеет выходящих дуг.
Вершины нумеруются, начальная вершина всегда имеет
метку 0.
Схема называется правильной, если в ней не используются пе-
ременные, значения которых не определены.
Граф схемы программ из табл. 6.1 представлен на рис. 6.1. Вершины всех операторов изображены в виде прямоугольников, кроме вершины-распознавателя, которая представлена овалом. Вершины пронумерованы от 0 до 4, и внутри них записаны сами опе­раторы.
68
Рис. 6.1. Граф схемы программ из табл. 6.1
Другим способом задания стандартной схемы является пред­ставление ее в линейной форме. Фактически мы уже кратко познако­мились с этим способом в примере из табл. 6.1, но теперь рассмотрим его более подробно.
Стандартная схема в линейной форме – это последова­тельность инструкций, которые строятся по следующим правилам:
1. Если начальная вершина содержит оператор start(x1,..., х
), а
n
ее выходная дуга ведет к вершине с меткой L, то соответствующая ин­струкция
0: start(x1,..., хn) goto L.
2. Если заключительная вершина обладает меткой L и содер-
жит оператор stop(1,..., n), то соответствующая инструкция
L: stop(1,..., n).
3. Если вершина с меткой L является преобразователем с опера-
тором х:=, а ее выходная дуга ведет к вершине с меткой L1, то соответ­ствующая инструкция
L: х:= goto L1.
4. Если вершина с меткой L является распознавателем с усло-
вием p(1,..., n), чья выходящая дуга с пометкой 1 ведет к вершине с меткой L1, а выходящая дуга с пометкой 0 – к вершине с меткой L0, то соответствующая инструкция
L: if p(1,..., n) then L1 else L0.
69
5. Если вершина с меткой L представляет собой петлю, то ей
соответствует инструкция
L: loop.
Построим теперь линейную форму для схемы программ P1 и P2 из табл. 6.1 в полном соответствии с представленными правилами:
0: start(x, n) goto 1, 1: у:=a goto 2, 2: y:=f (x, y) goto 3, 3: if p(y, n) then 2 else 4, 4: stop(y).
Видно, что получившаяся запись перегружена лишними мет­ками и ссылками на метки. В большинстве случаев в данном примере и так понятна последовательность выполнения инструкций. Поэтому рациональнее применять сокращенную запись линейной формы, где ненужные метки и ссылки опущены:
start(x, n), у:=a, 2: y:=f(x, y), if p(y, n) then 2 else 4, 4: stop(y).
Представленная схема является более компактным и строгим вариантом схемы, которая дана в табл. 6.1.
6.3. Интерпретированная стандартная схема программы
Как мы увидели, стандартная схема, вообще говоря, не являет­ся записью алгоритма. Она моделирует структурные свойства программ без учета семантики вычислений. Один из способов по­строения семантической теории схем программ основан на понятии интерпретации, или интерпретированной схемы.
Пусть задан некоторый базис B класса стандартных схем. Интерпретацией базиса B в области интерпретации D называется функция I, которая строится по следующим правилам:
1. Каждой переменной х из базиса B функция I ставит в соот-
ветствие некоторый элемент d = I (х), d D.
70
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]