соседями две выбранные страны. Предположим, вы хотите знать, граничат ли между собой Германия и Испания. Запрос формулируется так:
not (border("Germany", "Spain")).
Ответом на запрос явится True, так как согласно имеющимся в базе данных фактам, эти страны общей границы не имеют. Рассмотрим теперь другой запрос:
not (border("France", "Italy")).
Ответом на него будет False, так как Франция и Италия соседи.
*Упражнение
3.6.Переделайте программу для работы с внешними целями. В
ответ на приглашение Goal: введите not(border("Spain","Italy")).
Каким будет ответ ?
3.3.6 Использование составных объектов
Объекты утверждений представляют собой данные, тип же простых объектов ограничен 6 типами доменов. Рассмотрим такой пример утверждения:
owner("Mary","Garfield"). /* У Мери есть Гарфильд */
Первый объект Mary имеет простую структуру; он представляет сам себя. То же можно сказать и про объект Garfield. Любой объект, представляющий сам себя, называется простым объектом. Аналогично, структура, состоящая из простых объектов, называется простой структурой.
Утверждение owner отражает тот факт, что Mary обладает Garfield, который может быть либо именем домашнего животного Mary, либо названием книги. Для разделения этих случаев утверждение можно записать в форме, более определенно описывающей объект:
owner("Mary",pet("Garfield")). /* У Мери есть любимец - Гарфильд */ owner("Mary",book("Garfield")). /* У Мери есть книга - "Гарфильд" */
Объект, представляющий другой объект или совокупность объектов, называется составным объектом. Записанные же таким образом предикаты owner называются составными структурами, поскольку они скомпонованы из составных объектов. В данном примере pet представляет Garfield в первом утверждении, в то время как book - во втором, здесь pet и book являются составными объектами. Отметим, что объекты, которые они представляют, заключены в скобки.
Утверждение likes("Tom",apples,orange,banana).
констатирует, что Том любит фрукты: яблоки, апельсины и бананы. Все эти три вида фруктов можно объединить в отдельной структуре:
fruits(apples,orange,banana).
В результате появляется составной объект, который поясняет отноше-
ние:
likes("Tom",fruits(apples,orange,banana)).
(Oбратите внимание на двойные скобки в конце утверждения.)
56
Терм fruits в этом утверждении называется функтором. Функтор является первым термом составного объекта. Функтор составного объекта есть на самом деле предикат, хотя он и вставлен внутрь другого предиката. Главным функтором здесь является предикат likes.
Для облегчения написания утверждений и предикатов в данной форме Турбо-Пролог позволяет объявлять составные объекты в разделе domains. Для настоящего примера описаниями будут служить
domains
personal_liking = fruits(type1,type2,type3) type1,type2,type3 = symbol
Имя домена personal_liking является именем составного объекта, образованного при помощи функтора fruits. Имя fruits представляет одновременно составной объект и функтор. Если объекты структуры принадлежат к одному и тому же типу доменов, то этот объект называется однодоменной структурой. Структура с объектами apples, peaches и oranges (все типа symbol), является однодоменной структурой. Если структура содержит объекты разных типов, она называется многодоменной структурой. Примером тому совокупность объектов apples, r и 16. Здесь apples имеет тип symbol, r - тип char, 16 - тип integer. Таким образом составной объект является определенной структурой доменов. Каждая структура предполагает особое представление фактов в базе данных. Структура обеспечивает средство сортировки объектов по категориям. Ссылки на доменную структуру осуществляются по имени функтора.
*Функторы и доменные структуры
Программа "Библиотека" (листинг 3.7) демонстрирует использование
доменной структуры с именем personal_library. Эта структура содержит сведения о книгах из личных собраний.
____________________________________________________________
Листинг 3.7
/* Программа: Библиотека */ /* Назначение: Демонстрация одноуровневого составного */
/* объекта. */ domains
personal_library = book (title, author, publisher, year) /* персональная библиотека = книга(название,автор,
издательство,год издания) */ collector, title, author, publisher = symbol
year = integer
predicates
collection(collector, personal_library)
/* коллекция (имя коллекционера, библиотека) */
clauses
57
collection(kahn, book("The Computer and the Brain", "von Neumann", "Yale University Press",1958)).
collection(kahn, book("Symbolic Logic", "Lewis Carroll", "Dower Publications",1958)).
collection(johnson, book("Database: A Primer", "C.J.Date", "Addison-Wesley",1983)).
collection(johnson, book("Problem-Solving Methods in AI", "Nils Nilsson", "McGraw Hill",1971)).
collection(smith, book("Alice in Wonderland",
"Lewis Carroll", "The New American Library",1960)). collection(smith, book("Fables of Aesop", "Aesop-Calder",
|
|
"Dover Publications",1967)). |
/***** |
конец программы |
*****/ |
_____________________________________________________________
Функтор структуры personal_library имеет имя book. Описание таково: personal_library = book(title, author ,publisher, year)
collector, title, author, publisher = symbol year = integer
Предикат, использующий эту структуру, определяется так: collection (collector, personal_library)
Описание содержит два имени объектов. Первое имя относится к обычному объекту, второе - к структуре из нескольких объектов.
Использование доменной структуры упрощает структуру предиката. Если не использовать конструкцию доменной структуры, то программы требовала бы такого описания предиката collection:
collection(collector, title, author, publisher, year)
В этом описании 4 последних объекта обозначают атрибуты книги. Правило, которое оперирует с персональными библиотеками рассматривало бы эти 4 последних объекта как независимые сущности, что сделало бы код программы более сложным.
Данная программа использует внешнюю цель. Для того, чтобы узнать, какие книги принадлежат Смиту, необходимо ввести такое целевое утверждение:
Collection (smith, Books).
Объект smith является частным значением из домена collector, а Books - свободной переменной. Цель заключается в отыскании всех книг, принадлежащих Смиту.
Предположим теперь, что Вы хотите знать имена владельцев и названия книг, напечатанных в 1967 году. Цель для поиска этой информации выглядит следующим образом:
collection(Collector,book(Title,_,_,1967)).
Здесь свободными переменными являются уже Сollector и Title. Подчеркивание (_) указывает на то, что Вас не интересуют объекты с родовыми
58
именами author и publisher. (Напомним, что подчерк замещает собой анонимную переменную.)
Следующие два упражнения познакомят Вас с использованием целевых утверждений различных типов.
*Упражнения
3.7.Вы хотите задать вопрос: Как зовут коллекционера, которому принадлежит книга под названием "Database.A Primer." ? Этот запрос в ТурбоПрологе формулируется в виде
collection(Collector,book("Database:A Primer",_,_,_)).
Что получится ?
3.8.Вы хотите задать вопрос: Каковы названия книг, опубликованных после 1980 года ? Целевая конструкция для этого вопроса выглядит так:
collection(_,book(Title,_,_,Year)),Year > 1980.
Что получится ?
Программа "Библиотека - 2" (листинг 3.8) демонстрирует использование трехуровневой доменной структуры и четырехуровневой предикатной.
____________________________________________________________
Листинг 3.8
/* Программа: Библиотека -2 */ /* Назначение: Демонстрация двухуровневого составного */
/* объекта. */ domains
personal_library = book(title,author,publication) publication = publication(publisher,year) collector,title,author,publisher = symbol
year = integer
predicates collection(collector,personal_library)
clauses collection("Kahn",
book("The Computer and the Brain", "von Neumann",
publication("Yale University Press", 1958))). collection("Kahn",
book("Symbolic Logic", "Lewis Carroll",
publication("Dower Publications", 1958))). collection("Johnson",
book("Database: A Primer", "C.J.Date", publication("Addison-Wesley", 1983))).
59
collection("Johnson",
book("Problem-Solving Methods in AI", "Nils Nilsson", publication("McGraw Hill", 1971))).
collection(smith,
book("Alice in Wonderland", "Lewis Carroll", publication("The New American Library", 1960))).
collection(smith, book("Fables of Aesop", "Aesop-Calder",
publication("Dover Publications", 1967))). /***** конец программы *****/
_____________________________________________________________
Программа "Библиотека - 2" использует те же данные, что и программа "Библиотека". Однако, здесь publisher и year являются объектами publication - функтора третьего уровня. Описание доменов выглядит так:
personal_library = book(title,author,publication) publication = publication(publisher,year) collector,title,author,publisher = symbol
year = integer
Описание предикатов и утверждений в точности совпадает с описаниями из предыдущей программы, т. е. все отличие заключается только в описании доменов. Функторы здесь - book и publication, причем publication является компонентом функтора book. Усилия и время, затраченные при разработке доменных и предикатных структур с лихвой вознаградят Вас удобством пользования созданной Вами базы данных. Чем больше функторов, тем более определенные запросы можно адресовать базе данных; а именно такие запросы, вне всякого сомнения, представляют наибольший интерес.
*Упражнения
3.9.Запустите на счет программу "Библиотека - 2" и введите внешнюю цель в виде
collection(smith,Books).
или в виде
collection(Collector,book(Title,_,publication(_,1967))).
Окажется ли среди перечисленных на экране книг хотя бы одна из собрания
Kahn ?
3.10. Измените описание структур программы "Библиотека -2". Поместите объекты title и author в подструктуру с именем volume, которая определяется как
volume = volume(author,title)
Не забудьте привести в соответствие синтаксис утверждений. Запустите эту модифицированную программу. Теперь Вы сможете обращаться к базе данных несколько иначе. Попробуйте ввести такую цель:
60