ботке программы такой способ записи цели более предпочтителен, так как он упрощает эту самую запись. Особенно полезным он бывает тогда, когда программа имеет много разных подцелей, включающих в себя достаточно сложные операции. С точки зрения человека, лишь использующего эту программу, такой способ также более предпочтителен, так как упрощает процедуру запросов.
Правила в Турбо-Прологе записываются в разделе утверждений. Программа может содержать достаточно много правил, вырабатывающих различные заключения. Эффект введения правил точно такой же, как если бы программа содержала большое число утверждений-фактов. В программе "Родственники", например, можно в раздел clauses ввести еще ряд правил в дополнение к уже определенным. Предположим, что Вы хотите узнать имя сына. Этот запрос оформляется при помощи правила:
who_is_the_son if son(parents,_,_), male(Son),
write("The son is ",Son,"."), nl.
Это правило можно поместить в раздел clauses и заменить этим правилом целевое утверждение. Когда при запуске программы новое правило будет испытано, на экране появится надпись "The son is Sam".
Подобным образом можно ввести еще достаточное количество правил. Правила можно будет активизировать выборочно путем использования их в целевой конструкции. Возможность Турбо-Пролога выбирать нужные правила делает программу более гибким и мощным инструментом. Важным непосредственным приложением данного средства программирования является возможность задания запросов в форме правил, а также возможность "запасать" эти правила для использования при дальнейшей работе с базой данных. Примеры этого приложения будут приведены в главах 9 и 10.
*Упражнение
3.4.Введите программу "Родственники" и запустите ее на счет, чтобы убедиться в правильности набивки. Модифицируйте программу, введя правило определения имени брата. Цель изменений состоит в получении сообщения о том, что Сэм является братом Дебби.
3.3.4 Простые базы данных
Программа "Подбор партнера" (листинг 3.5) демонстрирует использование правил для получения информации в результате поиска соответствия по модели среди совокупности фактов. Эта программа является упрощенным прототипом программы для службы знакомств. Она содержит сведения о 7 мужчинах по параметрам: рост, цвет волос, класс машины. Единственным доменом программы является домен man.
_____________________________________________________________
51
Листинг 3.5
/* Программа: Подбор партнера |
*/ |
|
/* Назначение: Демонстрация конструкции правила. */ |
||
domains |
|
|
man = symbol |
|
|
predicates |
|
|
choice(man) |
|
|
short_height(man) |
/* мужчина низкого роста */ |
|
medium_height(man) /* мужчина среднего роста */ |
||
tall_height(man) |
/* мужчина высокого роста */ |
|
black_hair(man) /* мужчина - брюнет */ |
||
brown_hair(man) |
/* мужчина - шатен */ |
|
blond_hair(man) /* мужчина - блондин */ |
||
old_car(man) |
/* владелец старого автомобиля */ |
|
new_car(man) |
/* владелец нового автомобиля */ |
|
sports_car(man) /* владелец спортивного автомобиля */ kathy_choice(man)
who_is_the_choice
goal
who_is_the_choice.
clauses
/* факты */ choice(bill). choice(jim). choice(mark). choice(robert). choice(willy). choice(tom). choice(frank). short_height(bill). short_height(tom). medium_height(bill). medium_height(tom). tall_height(jim). tall_height(robert). tall_height(frank). black_hair(bill). black_hair(willy). brown_hair(jim). brown_hair(tom). blond_hair(mark). blond_hair(robert).
52
blond_hair(frank). new_car(bill). new_car(willy). new_car(frank). old_car(mark). old_car(tom). sports_car(jim). sports_car(robert). /* правила */
who_is_the_choice :- kathy_choice(Choice),
write("Kathy's choice is ",Choice,"."), nl.
kathy_choice(Choice) :- choice(Choice), tall_height(Choice), blond_hair(Choice), sports_car(Choice).
/***** конец программы *****/
_____________________________________________________________
В разделе clauses 7 утверждений предиката choice содержат имена bill, jim, mark, robert, willy, tom и frank. Утверждения с предикатами short_hair, medium_height, tall_height, black_hair, brown_hair, blond_hair, new_car, old_car и sports_car также содержат эти мужские имена. Целью программы является отыскание мужчины, соответствующего вкусам некой kathy: высокого роста, блондина, обладателя спортивного автомобиля.
В случае обнаружения мужчины, обладающего перечисленными свойствами, программа должна напечатать его имя. Правилом для поиска служит
kathy_choice(Choice) :- choice(Choice), tall_height(Choice), blond_hair(Choice), sports_car(Choice).
Назначение правила заключается в том, чтобы найти среди утверждений choice хотя один объект, который одновременно является объектом еще трех атрибутных утверждений: tall_height, blond_hair, sports_car.
Вначале данное правило присваивает переменной Сhoice значение одного из объектов утверждения choice. Как Вы можете вспомнить из обсуждения утверждений likes, Турбо-Пролог просматривает утверждения с нужным предикатом, начиная с первого; следовательно, при первой попытке переменная Choice примет значение bill. Затем правило попытается найти соответствие этого значения одному из объектов утверждений первого из
53
атрибутных предикатов, tall_height. Так как такого соответствия нет, то Тур- бо-Пролог откатывается к следующему утверждению choice и делает еще одну попытку. Теперь значением Choice становится jim. jim удовлетворяет запросу kathy т. к. обладает высоким ростом, поэтому Турбо-Пролог пытается найти соответствие этого значения утверждениям blond_hair. Ввиду того, что эта попытка оканчивается неуспехом, весь процесс повторяется с третьим утверждением choice. Повторы будут происходить до тех пор, пока не будет найдено значение Choice, удовлетворяющее всем трем подцелям
tall_height(Choice), blond_hair(Choice), sports_car(Choice).
Имя избранника Вы сможете назвать, если просмотрите листинг программы.
*Упражнение
3.5.Модифицируйте программу "Подбор партнера", написав правило для отыскания имени высокого мужчины, блондина, владельца нового автомобиля.
3.3.5 Отрицание
Помимо принадлежности одному и тому же домену, некоторые объекты могут иметь еще некоторое число общих атрибутов. Например, определенные страны Европы имеют общие между собой границы, в то время как другие их не имеют. Предикатом для представления этого отношения служит
border(country,country)
Тот факт, что "Германия и Франция имеют общую границу", можно представить в виде утверждения
border("France", "Germany").
Франция с Германией имеют общую границу, так же как и Франция с Испанией, и Франция с Италией.
Шесть утверждений задают все возможные пары четырех выбранных европейских стран:
euro_pair("France","Germany"). euro_pair("France","Spain"). euro_pair("France","Italy"). euro_pair("Germany","Spain"). euro_pair("Germany","Italy"). euro_pair("Spain","Italy").
Утверждения для стран с общей границей выглядят так: border("France","Germany"). border("France","Spain"). border("France","Italy").
Предположим теперь, что вы хотите определить, какие из стран не имеют общей границы. Вместо того чтобы выдавать на экран все пары стран с общей границей, а потом визуально искать все пары, не попавшие в этот список, лучше воспользоваться более простым и эффективным средством -
54
отрицанием. Отрицание предиката border задается при помощи предиката not:
not(border(Country1,Country2)).
Этот предикат выдает все пары не граничащих друг с другом стран. Программа "Пары стран Европы" (листинг 3.6) - это законченная программа на Турбо-Прологе для решения поставленной задачи.
_____________________________________________________________
Листинг 3.6
/* Программа: Пары стран Европы Файл: PROG0306.PRO */ /* Назначение: Демонстрация работы предиката отрицания. */ /* Указание: Цель - внутренняя. */
domains
country = symbol
predicates euro_pair(country,country) border(country,country) find_non_border_pair
goal
find_non_border_pair.
clauses
/* факты */
euro_pair("France","Germany"). euro_pair("France","Spain"). euro_pair("France","Italy"). euro_pair("Germany","Spain"). euro_pair("Germany","Italy"). euro_pair("Spain","Italy").
border("France","Germany"). border("France","Spain"). border("France","Italy").
/* правила */ find_non_border_pair :-
euro_pair(X,Y), not(border(X,Y)), write(X," - ",Y),nl.
/***** конец программы *****/
_____________________________________________________________
При программировании на Турбо-Прологе отрицания иногда бывают удобны для логического вывода неких фактов из уже имеющихся в базе данных. И вообще, использование предиката not в конструкции правила зачастую дает возможность ввести в программу элементы логики. Например, вопрос с отрицанием можно использовать для определения того, являются ли
55