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

Языки программирования. Концепции и принципы

.pdf
Скачиваний:
2
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
Реляционное программирование (модель Р)
касаться вовсе не того, КАК вычислять, а, например, того, ЧТО именно известно о потенциальных исходных данных и результатах таких вычислений.
Такие знания часто называют «непроцедурными», желая подчеркнуть их от
личие от процедурных. Однако если стараться исходить из собственных свойств такого рода знаний, то, заметив, что они касаются обычно фактов и отношений между объектами проблемной области, лучше называть их «логическими», или «реляционными» (от англ. relation – отношение).
341
4.2. Ключевая идея
Важно заметить, что если бы удалось отделить реляционные знания от процедур ных, возникла бы принципиальная возможность освоить новый уровень абстрак ции со всеми вытекающими из этого преимуществами для технологии решения задач. Ведь реляционное представление знаний о классе задач – абстракция от способа (алгоритма, процедуры) решения этих задач (и, следовательно, может об служивать самые разнообразные такие способы).
Более того, возникает соблазн разработать универсальный способ решения
произвольных задач из некоторой предметной области, параметром которого слу жит реляционное представление знаний об этой области.
Это и есть ключевая идея реляционного подхода. Другими словами, в этом
подходе привычное программирование как деятельность по созданию алгоритмов и представлению знаний о них в виде программ процедурного характера стано вится совершенно излишним. Программирование сводится к представлению ре ляционных знаний о некоторой предметной области (например, о родственных отношениях людей). Такое представление совместно с представлением данных о конкретной задаче из рассматриваемой области (например, указанием конк ретного человека) служит аргументом для универсального алгоритма, выдающе го решение этой конкретной задачи (например, список племянников указанного человека).
Основное достижение – в том, что переход к новой задаче (который при тради
ционном подходе потребовал бы создания новой программы), например к задаче о списке всех родных теток заданного человека, не потребует никакого програм мирования! Достаточно правильно сформулировать задачу (то есть правильно представить в реляционном стиле знания о ее исходных данных и ожидаемых результатах).
Конечно, чтобы она оказалась практичной, нужно выполнить целый ряд требо
ваний. К ним мы еще вернемся.
4.3. Пример
Представим реляционные знания о родственных отношениях. Другими словами, опишем «мир» родственных отношений. Содержательно это будет, конечно, очень упрощенная модель реального мира человеческих отношений.
342
Перспективы языков программирования
4.3.1. База данных
ô1) (мужчина, Иван) – Иван – мужчина ф2) (мужчина, Степан) фЗ) (мужчина, Николай) ф4) (мужчина, Кузьма) ф5) (женщина, Марья) – Дарья – женщина фб) (женщина, Дарья) ф7) (родитель, Степан, Николай) – Степан – родитель Николая ф8) (родитель, Дарья, Кузьма) – Дарья – родитель Кузьмы ф9) (родитель, Иван, Дарья) ф10) (родитель, Иван, Степан)
Итак, мы пользуемся простейшим языком представления реляцонных знаний. Представлены три конечных отношения – «мужчина», «женщина» и «родитель». Два первых – одноместные (унарные), третье – двухместное (бинарное). Отноше ние представлено конечным множеством кортежей, каждый из которых представ ляет элемент отношения – элементарный факт, касающийся некоторых именато мов. При этом имя отношения всегда занимает первую позицию в кортеже. Позиция атома в кортеже, конечно, существенна.
Например, (родитель, Дарья, Кузьма) и (родитель, Кузьма, Дарья) представ ляют разные факты.
Совокупность отношений называется реляционной базой данных (БД).
4.3.2. База знаний
Вместе с тем содержательный смысл отношений пока никак нами не представлен. Его можно проявить только за счет указания связей между отношениями! Пред ставим некоторые из таких связей так называемыми предложениями. Содержа тельно предложения служат правилами вывода, позволяющими строить одни от ношения из других.
Определим правила вывода отношений «брат», «сестра», «общий_родитель», «дядя» и «тетя».
п1) (брат, X, Y) (мужчина, X) (общие_родители, X, Y) п2) (сестра, X, Y) (женщина, X) (общие_родители, X, Y) пЗ) (общий_родитель,Х,У) (родитель,Z,Х) (родитель,Z,Y) п4) (дядя, X, Y) (мужчина, X) (родитель, Z,Y) (брат, X, Z) п5) (тетя, X, Y) (женщина, X) (родитель, Z,Y) (сестра, X, Z)
Формально предложение – это кортеж кортежей, в которых допускаются не только атомы, но и переменные. Переменные будем обозначать большими латинс кими буквами. Совокупность предложений называется базой знаний (БЗ) (иногда этим термином называется совокупность предложений вместе с БД; во всяком слу чае, именно наличие правил вывода отличает базу знаний от базы данных).
Нетрудно догадаться, что предложения позволяют выводить новые факты из фактов, уже содержащихся в БД. Например, можно вывести факты
Реляционное программирование (модель Р)
(общие_родители, Степан, Дарья)
(общие_родители, Дарья, Степан)
(брат, Степан, Дарья)
343
4.3.3. Пополнение базы данных (вывод фактов)
Точный смысл правил вывода (семантику реляционного языка) можно объяснять поразному. Начнем с метода, никак не учитывающего конкретную задачу, кото рую предполагается решать. Назовем его разверткой БД. Сформулируем сначала суть развертки, а потом продемонстрируем ее на примере нашей БЗ.
Суть развертки. Первый кортеж каждого правила интерпретируется как
«следствие» из «условий», представленных остальными кортежами этого прави ла. Наглядно это можно выразить формулой
Т <== В1&...&Вn,
где Т – первый кортеж (следствие, теорема), a Bi – условия (посылки, аксиомы, факты).
Цель развертки: построить БД, содержащую все факты, выводимые из фактов
исходного состояния БД посредством правил вывода из БЗ.
Полная развертка состоит из последовательности циклов, в каждом из кото
рых каждое предложение поочередно применяется к текущему состоянию БД. Вначале текущим состоянием считается исходное состояние БД.
Очередное применение предложения состоит из последовательности всех раз
верток, выполняемых этим предложением при определенной подстановке атомов вместо переменных (поскольку число переменных и атомов конечно, то и число таких разверток конечно; вместо каждой переменной подставляется один и тот же атом).
Развертка состоит в том, что если все кортежиусловия содержатся в соответ
ствующих отношениях текущего состояния БД, то кортежследствие (после заме ны в нем переменных атомами) пополняет соответствующее отношение (если его еще там нет).
Развертка завершается, когда очередной цикл не добавляет ни одного нового
кортежа ни в одно отношение.
Заметим, что развертка завершается при любой исходной БД. (Почему?) Рассмотрим пример. Первая развертка правил (п1) и (п2) со стр. 342 пуста (так как отношение «об
щие родители» пусто). Первая развертка правила (п3) при Z=Иван пополняет от ношение «общие_родители» кортежами
(общие_родители, Степан, Дарья) и (общие_родители, Дарья, Степан).
Первая развертка правил (п4) и (п5) со стр. 342 также пуста (так как отноше
ния «брат» и «сестра» пока попрежнему пусты).
344
Во втором цикле «общие_родители» уже не пусто, и развертка правила (п1) добавляет кортеж
(брат, Степан, Дарья),
а правило (п2) добавляет кортеж
(сестра, Дарья, Степан).
В этом же цикле развертка правил (п4) и (п5) добавляет кортежи
(дядя, Степан, Кузьма) (тетя, Дарья, Николай).
Так как третий цикл ничего нового не добавляет, развертка завершается.
Теперь все готово для решения конкретных задач из предметной области, зна ние о которой представлено БЗ.
Перспективы языков программирования
4.3.4. Решение задач
Конкретная задача формулируется в виде кортежа (обычно с переменными), вы деляемого знаком вопроса. Например:
?(дядя, Q, Кузьма).
Вопрос рассматривается в качестве образца, для которого требуется подобрать кортежи из отношений БД, получаемые из образца подходящей заменой перемен ных. Решением задачи считается перечень всех таких кортежей. Например, реше ние нашей задачи имеет вид
(дядя, Степан, Кузьма).
Содержательный смысл решения очевиден (спрашивается, кто дядя Кузьмы; ответ: Степан). Понятно, что несложно выдавать ответ и в виде, например,
Q = Степан.
Нетрудно понять, что таким образом можно решить любую задачу из «мира родственных отношений» Ивана, Степана, Николая, Кузьмы, Марьи и Дарьи.
Например:
?(тетя, R, Николай) R = Дарья ?(Q, Степан, Дарья) Q = общие_родители или Q = брат.
Итак, показано, как можно представить реляционные знания для целого клас са задач таким образом, что решение конкретной задачи не требует никакого про граммирования. Человек описывает мир на языке представления знаний, затем человек ставит задачу на языке запросов, а компьютер дает решение задачи, пользуясь универсальным решающим алгоритмом (в нашем случае это алгоритм развертки). Отличие от обычной реляционной БД – в БЗ, написанной на языке представления знаний.
4.3.5. Управление посредством целей
Если до сих пор мы стремились лишь объяснить семантику реляционного языка, то теперь пришло время подумать о его эффективности. Бросается в глаза, что
Реляционное программирование (модель Р)
345
развертка слишком расточительна с точки зрения потребностей конкретных за дач. Для ответа на запрос о дяде Кузьмы совершенно не требуются отношения «сестра» и «тетя», которые тем не менее и вычисляются, и хранятся в БД. Други ми словами, развертка готовит ответы сразу на все случаи жизни, чего нельзя себе позволить в реальных условиях.
Суть управления посредством целей. Поищем иной принцип использования
исходной БЗ, с тем чтобы по возможности делать лишь ту работу, которая необхо дима для решения конкретных задач.
Ясно, что лишняя работа делается изза того, что развертка никак не использу
ет постановку задачи (и даже ничего не «знает» о ней). Ключевая идея нового принципа использования БЗ в том и состоит, чтобы при попытке ответить на за прос анализировать те
и только те правила из БЗ, которые могут оказаться полез ными именно для этого запроса, этот «новый» принцип нам в сущности уже хо рошо знаком – это принцип пошаговой детализации «сверху вниз» – от исходной задачи к подзадачам (от исходной цели к подцелям).
Главное при управлении посредством целей – уметь выбирать такие подцели, которые действительно способствуют достижению цели верхнего уровня, и во время прекращать заниматься подцелями, которые оказались бесперспективны ми (с точки зрения цели верхнего уровня).
Уточнения и примеры. Постановка задачи считается первой текущей целью запросом. Затем БД и БЗ совместно используются для ответа на запрос. При этом последовательно анализируются следствия (первые кортежи) предложений БЗ и факты БД – тривиальные следствия. Следствие считается сопоставимым с запро сомцелью, если существует такая согласующая подстановка (значений вместо переменных запроса и следствия), в результате которой запрос совпадает со след ствием.
Например, следствие (дядя, X, Y) сопоставимо с запросом (дядя, Q, Кузьма), так как они совпадают после согласующей подстановки
X -> Q, Y -> Кузьма.
Дерево целей. Если найденное сопоставимое следствие оказывается фактом (то есть не содержит переменных), то цель считается достигнутой. Если же сопос тавимое следствие начинает некоторое предложение, то условия из этого предло жения становятся подцелями. Говоря точнее, подцелями становятся не сами усло вия, а результат применения к ним согласующей подстановки.
Например, из цели (дядя, Q, Кузьма) образуются связанные подцели
(мужчина, Q) (родитель, Z, Кузьма) (брат, Q, Z).
Обратите внимание на замену переменных в подцелях по сравнению с исход ными условиями. Связанность этих подцелей проявляется в том, что цель верхне го уровня может считаться достигнутой только при условии, что ее непосред ственные подцели достигаются совместно, при одной и той же согласующей подстановке.
Например, для цели (мужчина, Q) сопоставимым следствием оказывается факт (мужчина, Иван) при согласующей подстановке
346
Q -> Èâàí.
Перспективы языков программирования
А для цели (родитель, Z, Кузьма) сопоставимым следствием – факт (родитель,
Дарья, Кузьма) при согласующей подстановке
Z -> Дарья.
Тогда для достижения исходной цели и третья подцель должна быть достижи
ма при подстановке
Q -> Иван, Z -> Дарья.
Однако нетрудно убедиться, что подцель (брат, Иван, Дарья) не может быть
достигнута.
Действительно, из (п1) со стр. 342 возникает новая совокупность подцелей
(мужчина, Иван) (общие_родители, Иван, Дарья),
а затем из (п3) –
(родитель, Z, Иван) (родитель, Z, Дарья).
Однако ни для какого Z в БД нет факта, сопоставимого с первой из этих под
целей.
Итак, принципиально важный момент – что делать, когда для некоторой подце
ли найти согласующую подстановку не удается. Назовем такую ситуацию тупиком.
Тупики и перебор с возвратом. Конечно, такую подцель следует признать не
достижимой, так как для нее проанализированы все потенциально сопоставимые
следствия. Однако не исключено, что цель верхнего уровня всетаки достижима.
Ведь недостижимость конкретной ее подцели могла быть вызвана неудачным вы
бором либо подстановок в связанных подцелях, либо подстановки при переходе
от цели верхнего уровня к подцелям.
Например, для цели (мужчина, Q) другие сопоставимые следствияфакты – (мужчина, Степан), (мужчина, Николай) и (мужчина, Кузьма). Причем каждому из них соответствует своя согласующая подстановка.
Проблема тупиков в дереве подцелей решается классическим методом – так на зываемым перебором с возвратом (backtracking) потенциальных сопоставимых следствий и согласующих подстановок. Для его реализации нужно организовать так называемый стек возвратов, где и запоминать место сопоставимого следствия вместе с соответствующей согласующей подстановкой, с тем чтобы иметь воз можность продолжить поиск согласующей подстановки, когда возникнет тупик.
Например, в нашем случае придется вернуться к подцели (мужчина, Q) и вы брать другое следствиефакт (мужчина, Степан) при новой согласующей подста новке
Q -> Степан.
Тогда при той же подстановке с
Z -> Дарья
в качестве третьей подцели получим
(брат, Степан, Дарья),
что выводимо посредством (п1) с учетом (ф2), (пЗ), (ф9) и (ф10).
Реляционное программирование (модель Р)
Итак, исходная цель будет достигнута при Q = Степан и тем самым получено
решение задачи (обратите внимание: правило (п5) не было использовано).
Замечание. Управление посредством целей описано нами в значительной степени
в традиционном операционном стиле, хотя, конечно, был соблазн применить
реляционный стиль. Однако это именно соблазн, потому что даже если игнориро
вать проблемы читателя, которому о новом для него принципе рассказывают, опи
раясь на сам этот новый принцип, останутся содержательные проблемы – ведь опи
сывается именно определенная операционная семантика (простого реляционного
языка представления знаний), причем именно определенные операционные ее эле
менты существенны для
задумана. Сохранив в реляционном описании лишь семантическую функцию (то
есть связь знака с денотатом), выплеснем с водой и ребенка (оптимизацию ресур
сов для решения конкретной задачи). Это наблюдение подтверждает ту истину, что
природа знания разнообразна и различные его разновидности требуют адекватных
средств. Так что и реляционный стиль, который выглядит экономным и изящным
в одних случаях, может оказаться громоздким и неадекватным в других.
Вопрос. Какие еще источники неэффективности имеются в предложенном методе
поиска согласующей подстановки?
Подсказка. Например, общий метод перебора с возвратом не защищен от много
кратного анализа уже проанализированных подцелей.
Вопрос. Может ли развертка оказаться эффективнее перебора с возвратом?
той оптимизации времени и памяти, ради которой она
347
4.4. О предопределенных отношениях
Внимательный читатель, повидимому, заметил неестественность отношений, вводимых правилами (п1)–(п3) со стр. 342. Ведь по таким правилам несложно оказаться собственным братом или собственной сестрой. Конечно, следовало бы в каждое из упомянутых правил дописать условие, например (не_равно, X, Y).
Однако адекватно определить такое отношение в рамках простого реляцион
ного языка не удастся. Конечно, в принципе можно перечислить нужные факты, касающиеся конкретного набора атомов (хотя и это занятие не из приятных – ведь нужно указать все возможные упорядоченные пары различных атомов!). Могут помочь правила, учитывающие симметричность и транзитивность отноше ния «не_равно». Но это не избавит от необходимости при добавлении каждого но вого атома добавлять и «базовые» факты о его неравенстве всем остальным атомам.
Дело в том, что простейший реляционный язык не содержит никаких средств,
позволяющих построить отрицание некоторого утверждения, – отрицательный ответ на запрос представлен пустым множеством положительных ответов на него.
Пример с отношением неравенства в простейшем реляционном языке показа
телен в том смысле, что помогает понять фундаментальные причины появления в ЯП предопределенных (встроенных) средств. Так как неравенство нельзя адек ватно выразить средствами языка, приходится обходиться без явного определе ния такого отношения, считая его предопределенным (то есть фактически опреде ленным иными средствами, выходящими за рамки ЯП).
348
Конечно, в реальных ЯП не для всех предопределенных средств нельзя напи сать явные определения.
Вопрос. Какие еще соображения могут повлиять на перечень предопределенных средств?
Подсказка. Хорошо ли выражать умножение через сложение?
Мы рассмотрели лишь простейшие примеры «программирования» в реляци онном стиле. Из реальных ЯП, в которых этот стиль взят за основу, отметим оте чественный Реляп [25] и широко известный Пролог [26]. В последнем, правда, имеются встроенные средства, которые лишь называются отношениями, а на са мом деле служат для программирования во вполне операционном стиле.
Интересные результаты, способствующие применению Пролога в реляцион ном стиле, получены А. Я. Диковским.
Перспективы языков программирования
4.5. Связь с моделями МТ и Б
Интересно проследить связь реляционного программирования с ранее рассмот ренными моделями ЯП (заметим, что слово «модель» чуть выше использовалось нами в ином смысле). Стремясь к ясности, не будем бояться частично повторить ся в этом пункте. Зато станет прозрачнее математическая суть реляционного под хода (другими словами, будем более обычного уделять внимание математической позиции).
Итак, вернемся к исходной нашей цели – обеспечить абстракцию от програм мы. С позиций нашего курса можно прийти к ней разными путями. Укажем на два из них: от модели МТ и от модели Б.
4.5.1. Путь от модели Б
Основное математическое понятие в этой модели – функция из кортежей в корте жи. Программа – композиция функций.
Первая необходимая модификация на пути к модели Р – переход к более об щему математическому понятию – отношению. Так как необходимо обеспечить разрешимость, рассматриваются только конечные отношения.
Определение. Конечное отношение – именованное конечное множество кор тежей фиксированной длины. Длина кортежей называется местностью, или ар ностью отношения.
Для удобства положим, что имя отношения служит первой компонентой каж дого его кортежа. Тогда арность – на единицу меньше длины кортежей. Напри мер, отношение с именем «родитель» представлено совокупностью кортежей
(родитель, Иван, Степан) (родитель, Иван, Дарья) (родитель, Марья, Степан) (родитель, Петр, Иван)
Реляционное программирование (модель Р)
349
Содержательно это может означать, что Иван – родитель Степана, Петр – ро
дитель Ивана и т. д.
Вторая необходимая модификация. Вводится понятие БД. Определение. Реляционная база данных – это конечная совокупность конеч
ных отношений. (От англ. relation – отношение.)
Третья необходимая модификация. Вместо конкретных кортежей – образцы
с переменными и понятие согласующей подстановки (в точности как в модели МТ). Появляется возможность записать, например:
(родитель, X, Степан) (родитель, Марья, У).
Уже эта модификация позволяет легко задавать вопросы (ставить задачи) от
носительно БД. Каждый образец можно считать вопросом о содержимом БД (а именно о совокупности согласующихся с ним кортежей). Например, наш пер вый образец означает вопрос «Кто родитель Степана?», а второй – «Чей родитель Марья?». В нашей БД из четырех кортежей ответы будут соответственно
(родитель, Иван, Степан) и (родитель, Марья, Степан).
В сущности, если у нас есть общий алгоритм поиска согласования (а он есть –
ведь база конечная!), то мы достигли абстракции от программы, если считать за дачей вопрос, а моделью – БД. Мы скоро увидим, что это совершенно естественно.
Обратите внимание, сколь много значит удобная и мощная система обозначе
ний (какие разнообразные вопросы можно задавать с помощью переменных в об5 разцах). Скачок к простоте обозначений сравним с переходом от «арифметиче
ских» формулировок задач к алгебраическим.
Четвертая модификация. Образцы становятся условными. Определение. Условным образцом называется конечная последовательность
образцов. Первый из них называется следствием, а остальные – условиями.
Например, если бы в нашей БД были отношения
(мужчина, Иван) (мужчина, Степан) (мужчина, Петр)
и
(женщина, Марья) (женщина, Дарья),
то можно было бы задать условные вопросы
(родитель, X, Степан) (женщина, X) и (родитель, X, У) (мужчина, X) (женщина, У).
Ответы были бы
(родитель, Марья, Степан) и (родитель, Иван, Дарья).
Другими словами, второй и последующие образцы служат фильтрами образ
цаследствия. Согласующимся с условным образцом считается только такой кор теж, согласованный со следствием, для которого все фильтры истинны (то есть
350
фильтры можно согласовать при подстановке, согласующей этот кортеж со след ствием). Например, кортеж
(родитель, Иван, Степан)
не согласуется с последним условным образцом, так как при подстановке {X > Иван, У > Степан) невозможно согласовать второй фильтр (женщина, У).
Для поиска согласований с условными образцами используется перебор с воз вратом (backtracking), при котором последовательно проверяют возможность согласовать последовательные фильтры и при неудаче возвращаются к предыду щему фильтру с новым претендентом на согласование. Существенно использует ся конечность БД.
Пятая модификация. От условных образцов к правилампредложениям. Остался всего один принципиально важный шаг до реляционного языка представления знаний. Условный образец можно рассматривать как правило формирования базы данных.
Именно если существует согласующая подстановка, при которой все условия об разца истинны, а следствие ложно, то условный образец можно трактовать как приказ записать в базу данных кортеж, получаемый из следствия этой подстановкой.
Конечно, в системе программирования должны быть средства, позволяющие различать трактовки условного образца как вопроса и как правила. Скажем, мож но выделять правила спереди восклицательным знаком, а вопросы – вопроситель ным. Например, правило
! (дед, X, У) (родитель, X, Z) (родитель; Z, У) (мужчина, X)
порождает в нашей базе новое отношение
(дед, Петр, Степан) (дед, Петр, Дарья).
Теперь мы полностью готовы к объяснению абстракции от программы в реля ционном программировании.
Теория представляет собой соединение исходной БД (фактов) и БЗ – конеч ной совокупности правил (их называют правилами вывода, правилами порожде ния, хорновскими формулами, логическими соотношениями и т. п.). Описание модели представляет собой дополнительные факты и правила. В режиме порож дения модели все правила порождения применяются для построения пополнен ной базы, которая и считается построенной моделью. Теперь можно ставить зада чи на этой модели, задавая конкретные вопросы. Никакого программирования в обычном смысле не требуется – во всех случаях работают единые алгоритмы согласования образцов с кортежами.
Эта простая схема в практических реляционных языках (например, в Прологе) модернизируется для более рационального расходования ресурсов и удобства представления знаний.
Перспективы языков программирования
4.5.2. Путь от модели МТ
Опишем его короче, учитывая сказанное выше. Первая модификация – полем зрения служит вся БД, при этом отношения и кортежи представлены МТвыра жениями специального вида. Вторая модификация – МТпредложения превра
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]