Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Теория вычислительных процессов и структур. Учебное пособие
.pdf
2. Каждой константе а из базиса B функция I ставит в соот-
' WWx
ветствие некоторый элемент d = I (а), d D.
3. Каждому функциональному символу f
(n)
при n 1 функция I
ставит в соответствие всюду определенную функцию
(n)
F
= I(f
(n)
) : Dn D
(это значит, что n аргументов функции и ее значения принадлежат области интерпретации D).
4. Каждой логической константе р
(0)
функция I ставит в соот-
ветствие один из символов множества {0, 1}.
5. Каждому предикатному символу p
(n)
при n 1 функция I ста-
вит в соответствие всюду определенный предикат
(n)
P
= I(p
(n)
) : Dn {0, 1}.
Интерпретация называется конечной, если D – конечное множество.
Как можно заметить, определение интерпретации не уточняет
природу объектов множества D: она выбирается в зависимости от конкретной задачи.
Пусть S – схема в базисе B, а I – интерпретация этого базиса.
Тогда пара (S, I) называется интерпретированной стандартной схе-
мой, или программой.
Обозначим конечное множество переменных схемы S как Xs.
Это множество называется памятью схемы S.
Состоянием памяти программы (S, I) называется функция
W : Хs D, которая каждой переменной х Xs сопоставляет элемент
W(х) из области интерпретации D. Элемент W(х) называется значени-
ем переменной х в состоянии W.
Если два состояния памяти W и W' совпадают с точностью до
значений переменной х (т.е. y x, y Xs : W(y) = W'(y)), то исполь-
зуют запись
.
Если X = (х1, x2,…, хп) – некоторый набор переменных,
х1,…, хп X
, то W(X) = (W(х1), W(x2),…, W(хп)) – набор значений этих
s
переменных.
71

Начальным состоянием памяти Xs при интерпретации I называется такое состояние W0, для которого x Xs W0(х) = I(х).
Определим значение терма при интерпретации I и состоянии памяти W (будем обозначать его I (W)) по следующим правилам:
1) если = х, где х – переменная, то I (W) = W(х);
2) если = а, где а – константа, то I (W) = I(а);
3) если = f
(n)
(1, 2,…, n), где 1, 2,…, n – термы, то
I (W) = I(f
(n)
)(
(W),
1I
(W),…,
2I
(W)).
nI
Понять конструкцию в правой части этого выражения можно
следующим образом. Вместо функционального символа f
ляется его интерпретация – некоторая функция F
(n)
из области интер-
(n)
подстав-
претации D, обладающая n аргументами. Аргументами функционального символа f
няется своим значением при интерпретации I и состоянии W, и эти
значения используются в качестве аргументов функции F
(n)
были термы 1, 2,…, n. Теперь каждый из них заме-
(n)
.
Значение теста π при интерпретации I и состоянии памяти W
обозначается и определяется аналогичным образом:
π
(W) = I(p
I
(n)
)(
(W),
1I
(W),…,
2I
(W)).
nI
6.4. Протокол выполнения программы
Пусть дана программа (S, I). Пара и = (l, W), где l – метка вершины схемы S, а W – состояние ее памяти, называется конфигурацией
данной программы. Выполнение программы можно описать в виде последовательности конфигураций. Эта последовательность называется
протоколом выполнения программы.
Протокол строится следующим образом. Пусть дана последовательность конфигураций (u0, u1,… , ui, u
, …) для программы (S, I).
i+1
Будем обозначать i-ю конфигурацию протокола как ui = (ki, Wi), где
ki – соответствующая данной конфигурации метка вершины, а
Wi – состояние памяти. Тогда начальному состоянию памяти схемы S
при интерпретации I соответствует конфигурация u0 = (0, W0).
Рассмотрим некоторую i-ю конфигурацию протокола. Пусть
O – оператор схемы S, находящийся в вершине с меткой ki.
72

Если O – заключительный оператор stop(1,...,
i
x
i
WW
1
21
21
21
,0
,1
),(
ddесли
ddесли
ddP
), то протокол
n
конечен, и ui – последняя его конфигурация. Программа (S, I) останав-
ливается, а последовательность значений
1I (Wi
),
2I (Wi
),…,
nI (Wi
) на-
зывается результатом выполнения программы.
Если O не является заключительным оператором, то в протоколе существует следующая конфигурация: u
i+1
= (k
i+1
, W
). Здесь
i+1
возможны следующие варианты:
1. O – начальный оператор с выходящей дугой, ведущей к
вершине с меткой l. Тогда k
= l, а W
i+1
= Wi.
i+1
2. O – оператор присваивания x:= с выходящей дугой, веду-
щей к метке l. Тогда k
i+1
= l,
, W
(x) = I (Wi), т.е. в состоянии
i+1
памяти произошло единственное изменение – переменная x получила
новое значение.
3. O – условный оператор, для которого выполнено
π
) = Δ (Δ {0, 1}), а соответствующая Δ выходящая дуга ведет к
I (Wi
вершине с меткой l (т.е. при данной конфигурации проверка теста π
приводит к переходу к вершине с меткой l). Тогда k
4. O – оператор петли. Тогда k
= ki, W
i+1
= l, а W
i+1
= W
i+1
= Wi.
i+1
, и протокол
i
бесконечен.
Программа останавливается тогда и только тогда, когда протокол ее выполнения конечен. Иначе она зацикливается, и результат ее
выполнения не определен.
В качестве примера рассмотрим протокол выполнения
программ P1 и P2 из табл. 6.1.
Вначале зададим интерпретацию для первой программы. Область интерпретации для нее обозначим как D1. Она будет включать в
себя множество целых неотрицательных чисел. Функцию I определим
следующим образом:
I(x) = 2; I(n) = 8; I(y) = 0; I(a) = 1;
I(f) = F, где F : D2 D – функция умножения двух чисел:
F(d1, d2) = d1 d2, где d1, d2 D;
I(p) = P, где P : D2 {0, 1} – предикат вида
, d1, d2 D.
Тогда протокол выполнения программы P1 будет выглядеть
так, как это показано в табл. 6.2.
73

Таблица 6.2
Номер конфигурации
0 1 2 3 4 5 6 7 8
Метка
0 1 2 3 2 3 2 3 4
Значение x
2 2 2 2 2 2 2 2 2
Значение n
8 8 8 8 8 8 8 8 8
Значение y
0 1 2 2 4 4 8 8 8
21
21
21
||,0
||,1
),(
ddесли
ddесли
ddP
Номер
конфигу-
рации
0 1 2 3 4 5 6 7 8
Метка
0 1 2 3 2 3 2 3 4
Значение x
abc
abc
abc
abc
abc
abc
abc
abc
abc
Значение n
9 9 9 9 9 9 9 9 9
Значение y
ε ε abc
abc
abcabc
abcabc
abcabcabc
abcabcabc
abcabcabc
Протокол выполнения программы P1
Зададим интерпретацию для программы P2. Область интерпретации здесь будет состоять из объединения двух непересекающихся
множеств D = Di Ds, где Di – множество целых неотрицательных
чисел, а Ds – множество цепочек, состоящих из букв латинского алфавита. Построим функцию I:
I(x) = abc; I(n) = 9; I(y) = ;
I(f) = F, где F : D
2
Ds – функция конкатенации двух строк:
s
F(d1, d2) = d1 • d2, где d1, d2 Ds;
I(p) = P, где P : Ds Di {0, 1} – предикат вида
, d1 Ds, d2 Di.
Протокол выполнения программы P2 представлен в табл. 6.3.
Протокол выполнения программы P2
74
Таблица 6.3

Интерпретации переменных x и n для обеих программ мы вы-
2121
~~ SSSS
E
брали произвольно, смоделировав ситуацию ввода их начальных значений пользователем. Отметим также, что для обеих программ интерпретация переменной y является несущественной: какую бы I(y) мы не
выбрали, в любом случае переменной y в обеих программах будет
присвоено значение константы a.
Протоколы обеих программ конечны. Результатом программы
P1 является число 8, а программы P2 – строка abcabcabc.
6.5. Свойства стандартных схем программ
Стандартная схема S в базисе B называется тотальной,
если для любой интерпретации I базиса B программа (S, I) останавливается.
Стандартная схема S в базисе B является пустой, если для любой интерпретации I базиса B программа (S, I) зацикливается.
Стандартные схемы S1 и S2 функционально эквивалентны
(S1 ~ S2), если для любой интерпретации I базиса B программы (S1, I) и
(S2, I) останавливаются с одинаковым результатом, либо обе зацикли-
ваются. Отметим, что отношение эквивалентности введено для схем в
одном базисе. Если схема S1 соответствует некоторому базису B1, а
схема S2 – B2, то в качестве единого базиса для определения эквивалентности этих схем можно взять объединение базисов B1 и B2.
Некоторое отношение эквивалентности E, заданное для пар
стандартных схем, называется корректным, если S1, S2
. Другими словами, из отношения E следует функцио-
нальная эквивалентность схем, для которых оно имеет место.
Поиск разрешимых корректных отношений эквивалентности
представляет значительный интерес, т.к. функциональная эквивалентность алгоритмически неразрешима. Таким образом, возникает
проблема сужения понятия эквивалентности. Основным способом,
позволяющим достичь этой цели, является сравнение не функций,
реализуемых программами, а истории их вычисления в процессе выполнения. Детальность истории сама по себе имеет мало значения,
главное, чтобы можно было однозначным образом восстановить по
этой истории результат выполнения программы. Тогда программы,
истории которых совпадают, автоматически будут иметь совпадающие результаты, что и означает функциональную эквивалентность.
75

Рассмотрим кратко виды историй программы.
1. Операционная история. Представляет собой последователь-
ность преобразователей, выполняемых при работе программы.
2. Операционно-логическая история. По сравнению с операци-
онной историей дополняется распознавателями, пройденными по ходу
работы программы.
3. Информационный граф реализации программы. Вершины
графа – преобразователи. Вершина vi соединяется с вершиной v
, если
j
vj использует результат vi в качестве аргумента.
4. Информационно-логический граф реализации программы.
Информационный граф дополняется вершинами проходимых по ходу
работы программы распознавателей.
5. Термальное значение результирующих переменных.
Для каждого аргумента a любой вершины графа строится дерево,
включающее в себя все вершины, достижимые из a при движении навстречу дугам информационных связей. Это дерево может быть записано в виде некоторого терма и называется термальным значением
аргумента a.
6. Логико-термальная история реализации программы. К тер-
мальному значению результативных переменных добавляются пройденные по ходу работы программы распознаватели вместе с термальными значениями их аргументов. Логико-термальная история строится
по информационно-логическому графу.
6.6. Цепочка стандартной схемы
Конечный путь по вершинам схемы, ведущий от начальной
вершины к заключительной, а также бесконечный путь по вершинам
схемы, начинающийся с начальной вершины схемы, называется
цепочкой стандартной схемы. Пример цепочки для схемы с рис. 6.1:
(0, 1, 2, 30, 4).
В верхнем индексе для метки 3 указан 0. Это означает, что
дальнейшее построение цепочки продолжится по дуге 0 вершиныраспознавателя, помеченной 3. Таким образом, верхние индексы служат указателями на соответствующую исходящую дугу вершины распознавателя.
76

Последовательность операторов, помечающих вершины некоторой цепочки схемы, называется цепочкой операторов. Пример цепочки операторов для схемы с рис. 6.1:
(start(x, n); y:=a; y:=f (x, y); p0(y, n); stop(y)).
Смысл верхнего индекса при условном операторе такой же,
как было выше описано для вершин цепочки схемы. Не следует путать этот индекс с индексом местности, который заключается в скобки.
Пусть S – стандартная схема в базисе В, I – некоторая его интерпретация, (0, 1, k2, k3,...) – последовательность меток инструкций S,
расположенных в порядке их вхождения в конфигурации протокола
выполнения программы (S, I). Очевидно, что данная последовательность является цепочкой схемы S. Говорят, что интерпретация I
порождает (подтверждает) эту цепочку.
Цепочка стандартной схемы в базисе B называется допусти-
мой, если она подтверждается хотя бы одной интерпретацией этого
базиса.
Стандартная схема называется свободной, если все ее цепочки
допустимы.
Цепочка операторов называется допустимой, если она соответствует допустимой цепочке схемы.
6.7. Свободные интерпретации
Свойства тотальности и пустоты, а также отношение функциональной эквивалентности введены для множеств всех возможных
интерпретаций базиса. Это означает, что если мы хотим установить,
является ли некоторая схема S пустой, то нам придется устанавливать
этой свойство для любой интерпретации I. Множество всех интерпретаций очень велико, и потому такой подход оказывается малополезным. Поэтому вместо всего множества интерпретаций рассматривается подкласс свободных интерпретаций.
Справедливость высказываний о семантических свойствах стандартной схемы, оказывается, достаточно продемонстрировать для программ, получаемых только с помощью этого подкласса.
77

Все свободные интерпретации базиса В имеют одну и ту же
область интерпретации. Она совпадает со множеством Т всех термов
базиса В. Строится свободная интерпретация следующим образом:
1. Для любой переменной x из базиса В и для любой свобод-
ной интерпретации Ih этого базиса Ih(х) = х.
2. Для любой константы а из базиса В Ih(a) = a.
3. Для любого функционального символа f
В Ih(f
F
(n)
(n)
) = F
(1,..., n) = f
(n)
: Тn Т, где F
(n)
(1,..., n). Это означает, что функция F, используя
(n)
– словарная функция такая, что
(n)
(n 1) из базиса
функциональный символ f, по термам 1,..., n Т строит новый
терм.
Предикатному символу в свободной интерпретации сопоставляется произвольный предикат, отображающий T в {0, 1}. Таким образом, разные свободные интерпретации различаются лишь интерпретацией предикатных символов.
Интерпретация I базиса B и свободная интерпретация Ih базиса B называются согласованными, если π I(π) = Ih(π), где π – логическое выражение.
78

7. ОПИСАНИЕ СИНТАКСИСА И СЕМАНТИКИ
ЯЗЫКА ПРОГРАММИРОВАНИЯ
7.1. Проблема точного описания языка программирования
Одной из главных проблем, связанных с созданием и применением языка программирования, является его точное описание. Как уже
отмечалось ранее, для определения формального языка необходимы
алфавит, из элементов которого строятся его конструкции, и правила,
по которым это построение будет производиться. Для полного описания языка программирования также необходимо определить смысловую нагрузку соответствующих конструкций.
Итак, для определения языка программирования необходимо
задать:
1. Множество символов языка.
2. Синтаксис языка, который определяет правила составления
корректных программ как цепочек, состоящих из основных символов
языка.
3. Семантику языка, которая задает смысловые значения кон-
струкций языка.
Точное описание языка необходимо, во-первых, разработчикам
языковых процессоров. Языковой процессор – это программа,
осуществляющая перевод программы на языке программирования в
машинный код, который может быть выполнен на данном физическом
или виртуальном процессоре. Примерами языкового процессора являются компиляторы и интерпретаторы.
Вид и смысл языковых конструкций должны быть в точности
такими, как их задумал автор языка. Любые реализации языкового
процессора должны давать одинаковые результаты для одинаковых
программ.
Пользователю языка программирования также необходимо
точное определения этого языка, иначе он просто не сможет правильно понимать и использовать его конструкции.
Таким образом, описание языка программирования должно
быть достаточно полным, однозначным (не допускающим двусмысленных толкований) и непротиворечивым.
Естественный язык не слишком хорошо подходит для решения
поставленной задачи, т.к. его конструкции не обладают достаточной
однозначностью и непротиворечивостью: одна и та же фраза может
79

быть понята разными людьми по-разному, в зависимости от уровня их
знания, компетентности, мировоззрения, взгляда на проблему и т.д.
Поэтому возникает необходимость использования какого-то другого,
специального языка, который бы не обладал указанными недостатками.
Язык, предназначенный для описания другого языка, называется метаязыком. Метаязык задает систему обозначений, понятий
языка и образованных из них конструкций, позволяющих представить
описываемый язык с помощью определенных ранее понятий и отношений между ними.
7.2. Определение синтаксиса языка программирования
Определение синтаксиса языка программирования является
отправной точкой его разработки. Существует ряд методов, позволяющих представить синтаксис в формализованном виде. Некоторые
из них рассмотрены ниже.
7.2.1. Форма Бэкуса–Наура
В форме Бэкуса–Наура каждое определяемое понятие представляется с помощью металингвистической переменной. Ее значением может быть любая конструкция из некоторого множества, фиксированного для данного понятия.
Металингвистические переменные описываются с помощью
формы, состоящей из двух частей.
В левой части указывается сама металингвистическая переменная, которую необходимо определить. Она заключается в угловые
скобки «<» и «>», которые в данном случае считаются специальными
символами («метасимволами»), не принадлежащими к алфавиту рассматриваемого языка.
В правой части формы записываются все варианты определения описываемой конструкции. Каждый такой вариант представляет
собой цепочку, состоящую из символов языка и металингвистических
переменных. Варианты отделяются друг от друга символом «|», выполняющим роль логической операции «или». Между левой и правой
частью ставится символ «::=», который можно интерпретировать как
«по определению является».
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
