49514 (Язык логического программирования Visual Prolog), страница 5
Описание файла
Документ из архива "Язык логического программирования Visual Prolog", который расположен в категории "". Всё это находится в предмете "информатика" из , которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "информатика, программирование" в общих файлах.
Онлайн просмотр документа "49514"
Текст 5 страницы из документа "49514"
Можно превратить недетерминированные предложения в детерминированные, вставляя отсечения в тело правил, определяющих данный предикат.
-
Предикат not
Следующая программа ch04el0.pro (рис. 5.) демонстрирует, как вы можете использовать предикат not для того, чтобы выявить успевающего студента: студента, у которого средний балл (GPA) не менее 3.5 и у которого в настоящее время не продолжается испытательный срок.
domains
name = symbol
gpa = real
predicates
honor_student(name)
student(name, gра)
probation(name)
clauses
honor_student (Name) :-
student(Name, GPA),
GPA>=3.5,
not(probation(Name)).
student ("Betty Blue", 3.5).
student ("David Smith", 2.0).
student ("John Johnson", 3.7).
probation ("Betty Blue").
probation ("David Smith").
goal
honor_student (X) .
-
Программа ch04e10.pro
При использовании предиката not необходимо иметь в виду следующее:
Предикат not будет успешным, если не может быть доказана истинность данной подцели.
Это приводит к предотвращению связывания внутри not несвязанных переменных. При вызове изнутри not подцели со свободными переменными, Visual Prolog возвратит сообщение об ошибке: "Free variables not allowed in not or retractall" (Свободные переменные не разрешены в not или retract). Это происходит вследствие того, что для связывания свободных переменных в подцели, подцель должна унифицироваться с каким-либо другим предложением и выполняться. Правильным способом управления несвязанными переменными подцели внутри not является использование анонимных переменных.
Первый пример работает правильно:
likes (bill, Anyone) :-% Anyone — выходной аргумент
likes(sue, Anyone),
not(hates(bill, Anyone).
В этом примере Anyone связывается посредством likes (sue, Anyone) до того, как Visual Prolog делает вывод, что hates (bill, Anyone) не является истиной. Данное предложение работает корректно.
Если пример изменить таким образом, что обращение к not будет выполняться первым, то получите сообщение об ошибке: "Free variable are not allowed in not" (Свободные переменные в not не разрешены).
likes(bill, Anyone):-% Это не будет работать правильно
not(hates(bill, Anyone)),
likes(sue, Anyone).
Даже если вы замените в not (hates (bill, Anyone)) Anyone на анонимную переменную, и предложение, таким образом, не будет возвращать ошибку, все равно получите неправильный результат.
likes(bill, Anyone):- % Это не будет работать правильно
not(hates(bill, _)),
likes(sue, Anyone).
Это предложение утверждает, что Биллу нравится кто угодно, если неизвестно ничего о том, кого Билл ненавидит, и если этот "кто-то" нравится Сью. Подлинное предложение утверждало, что Биллу нравится тот, кто нравится Сью, и при этом Билл не испытывает к этому человеку ненависти.
Неверное использование предиката not приведет к сообщению об ошибке или к ошибкам в логике вашей программы.Простые и составные объекты
До сих пор мы работали только основными видами объектов данных Visual Prolog, таких как числа, идентификаторы и строки. Visual Prolog может создавать не только простые, но и составные типы.
-
5. Простые объекты данных
Простой объект данных — это переменная или константа. Не путайте это значение слова "константа" с символьными константами, которые вы определяете в разделе constants программы. То, что мы здесь называем константой, это нечто, идентифицирующее объект, который нельзя изменять: символ (char), число (integer или real) или атом (symbol или string).
Константы включают числа, символы и атомы. Числа и символы были рассмотрены ранее.
Атомы имеют тип идентификатор (symbol) или строка (string). Отличие между ними — главным образом вопрос машинного представления и реализации, и, в основном, оно синтаксически не заметно. Когда атом передается в качестве аргумента при вызове предиката, то к какому домену принадлежит атом — symbol или string -определяется по тому, как описан этот аргумент в декларации предиката.
Visual Prolog автоматически преобразует типы между доменами string и symbol, поэтому вы можете использовать атомы symbol в доменах string и наоборот. Однако принято считать, что объект в двойных кавычках принадлежит домену string, а объект, не нуждающийся в кавычках, домену symbol. Атомы типа symbol — это имена, начинающиеся со строчной буквы и содержащие только буквы, цифры и знак подчеркивания.
Атомы типа string выделяются двойными кавычками и могут содержать любую комбинацию литер, кроме ASCII-нуля (0, бинарный нуль), который обозначает конец строки атома.
Примеры строк и идентификаторов приведены в табл. 1.
-
Строки и идентификаторы
Атомы-идентификаторы | Атомы-строки |
food | "Jesse James" |
rick_Jones_2nd | "123 Pike street" |
fred_Flintstone_1000_Bс_Bedrock | "jon" |
a | "a" |
new_york | "New York" |
pdcProlog | "Visual Prolog, by Prolog Development Center" |
Так как string/symbol взаимозаменяемы, их отличие не существенно. Однако имена предикатов и функторы для составных объектов должны соответствовать синтаксическим соглашениям домена symbol.
-
6. Составные объекты данных и функторы
Составные объекты данных позволяют интерпретировать некоторые части информации как единое целое таким образом, чтобы затем можно было легко разделить их вновь. Возьмем, например, дату "октябрь 15, 1991". Она состоит из трех частей информации — месяц, день и год. Представим ее на рис. 1, как древовидную структуру.
-
Древовидная структура даты
Можно объявить домен, содержащий составной объект date:
domains
date_cmp = date(string,unsigned,unsigned)
а затем просто записать:
D = date("0ctober",15,1991) .
Такая запись выглядит как факт Пролога, но это не так — это объект данных, который вы можете обрабатывать наряду с символами и числами. Он начинается с имени, называемого функтором (в данном случае date), за которым следуют три аргумента.
Функтор в Visual Prolog — не то же самое, что функция в других языках программирования; это просто имя, которое определяет вид составного объекта данных и объединяет вместе его аргументы. Функтор не обозначает, что будут выполнены какие-либо вычисления.
Аргументы составного объекта данных могут сами быть составными объектами. Например, вы можете рассматривать чей-нибудь день рождения (рис. 2), как информацию со следующей структурой:
Рис. 2. древовидная структура даты рождения.
На языке Пролог это выглядит следующим образом:
birthday(person("Leo","Jensen"),date("Apr",14,1960))
-
Унификация составных объектов
Составной объект может быть унифицирован с простой переменной или с составным объектом (возможно, содержащим переменные в качестве частей во внутренней структуре), который ему соответствует. Это означает, что составной объект можно использовать для того, чтобы передавать целый набор значений как единый объект, и затем применять унификацию для их разделения. Например:
date("April",14,I960)
сопоставляется с X и присваивает X значение date ("April", 14,1960). Также
date("April",14,I960)
сопоставляется с date (Mo, Da, Yr) и присваивает переменным Мо = "April", Da=14 и Yr = 1960.
-
Использование нескольких значений как единого целого
Составные объекты могут рассматриваться в предложениях Пролога как единые объекты, что сильно упрощает написание программ. Рассмотрим, например, факт:
owns(john, book(“From Here to Eternity", "James Jones")).
в котором утверждается, что у Джона есть книга "From Here to Eternity" (Отсюда в вечность), написанная James Jones (Джеймсом Джонсом). Аналогично можно записать:
owns (john, horse (blacky) ) .
что означает:
John owns a horse named blacky.(У Джона есть лошадь Блеки.)
Если вместо этого описать только два факта:
owns (john, "From Here to Eternity"), owns(john, blacky).
то нельзя было бы определить, является ли blacky названием книги или именем лошади.
-
Объявление составных доменов
Рассмотрим, как определяются составные домены. После компиляции программы, которая содержит следующие отношения:
owns(john, book("From Here to Eternity", "James Jones")).
и
owns (John, horse (blacky) ).
вы можете послать системе запрос в следующем виде:
owns (John, X)
Переменная Х может быть связана с различными типами объектов: книга, лошадь и, возможно, другими объектами, которые вы определите. Отметим, что теперь вы не можете более использовать старое определение предиката owns:
owns (symbol, symbol)
Второй элемент более не является объектом типа symbol. Вместо этого вы можете дать новое определение этого предиката
owns(name, articles)
Домен articles в разделе domains можно описать так
domains
articles = book(title, author); horse(name)
Точка с запятой читается как "или" В этом случае возможны два варианта книга будет определяться своим заглавием и автором, а лошадь будет распознаваться своим именем Домены title, author и name имеют стандартный тип symbol.
К определению домена легко могут быть добавлены другие варианты.
-
Многоуровневые составные объекты
Visual Prolog позволяет конструировать составные объекты на нескольких уровнях. Например:
domains
articles = book(title, author);%Первый уровень
author= author(first_name, last_name) %Второй уровень
title, first_name, last_name = symbol%Третий уровень
При использовании составных объектов со многими уровнями часто помогает такое "дерево" (рис. 7):
-
Дерево многоуровневого составного объекта
-
Повтор и рекурсия
Компьютеры способны повторять одно и то же действие снова и снова, Visual Prolog может выражать повторение как в процедурах, так и в структурах данных. Идея повторяющихся структур данных может показаться странной, но Пролог позволяет создавать структуры данных, размер которых не известен во время создания.
-
Процесс повторения
Программисты на языках Pascal, Basic или С, которые начинают использовать Visual Prolog, часто испытывают разочарование, обнаружив, что язык не имеет конструкций for, while или repeat. В Прологе не существует прямого способа выражения повтора. Пролог обеспечивает только два вида повторения
-
откат, с помощью которого осуществляется поиск многих решений в одном запросе,
-
и рекурсию, в которой процедура вызывает сама себя.
Однако этот недостаток не снижает мощи Пролога. Фактически, Visual Prolog распознает специальный случай рекурсии — хвостовую рекурсию — и компилирует ее в оптимизированную итерационную петлю. Это означает, что хотя программная логика и выражается рекурсивно, скомпилированный код так же эффективен, как если бы программа была написана на Pascal или Basic.
-
Использование поиска с возвратом для организации повторов
Когда выполняется процедура поиска с возвратом (откат), происходит поиск другого решения целевого утверждения. Это осуществляется путем возврата к последней из проверенных подцелей, имеющей альтернативное решение, использования следующей альтернативы этой подцели и новой попытки движения вперед (см. пример ch06e01). Очень часто для этого используется директива fail.
predicates
country(symbol)
print_countries
clauses
country("England").
country("France").
country("Germany").
country("Denmark").
print_countries:-
country(X),
write(X),% записать значение Х
nl,% начать новую строку
fail.
print_countries.