Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методические указания по ИИС.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
3.88 Mб
Скачать

Принципы отката:

  1. Подцели нужно выполнять по порядку, сверху вниз.

Лабораторная работа № 1 определяет, каким предложением можно удовлетворить подцель согласно второму основному принципу отката:

  1. Предложения предиката проверяются по порядку следования в программе, сверху вниз.

Продолжение поиска происходит согласно третьему основному принципу отката:

  1. Если подцель соответствует голове правила, тело этого правила должно быть так же выполнено. Тело правила предоставляет новый набор подцелей, которые необходимо решить.

Согласно четвертому основному принципу отката:

  1. Цель считается выполненной, когда найден факт соответствующий каждой из крайних точек (листьев) целевого дерева.

Рассмотрим программу, которая содержит информацию (факты) об именах и возрасте некоторых игроков в теннисном клубе.

  1. Опишите раздел доменов. Задайте типы аргументов предиката.

child = symbol

age = integer

  1. Опишите раздел предикатов.

nondeterm player(child, age)

  1. Опишите раздел предложений.

player(peter, 9).

player(paul, 10).

player(chris, 9).

player(susan, 9).

Ваша программа должна выглядеть следующим образом:

DOMAINS

child = symbol

age = integer

PREDICATES

nondeterm player(child, age)

CLAUSES

player(peter, 9).

player(paul, 10).

player(chris, 9).

player(susan, 9).

Допустим, Вы используете Лабораторная работа № 1 для организации турнира по пинг-понгу между девятью летними спортсменами в теннисном клубе. Нужно устроить по две игры для каждой пары игроков клуба. Ваша цель состоит в том, чтобы найти все возможные пары игроков. Это может быть достигнуто с помощью следующей составной цели:

player(Person1, 9),

player(Person2, 9),

Person1<> Person2.

Это означает найти Person1 (9 лет) и Person2 (9 лет) так, чтобы Person1 и Person2 были разные люди.

Сначала Лабораторная работа № 1 будет искать решение первой подцели player(Person1, 9) и перейдет к следующей только после того, как первая подцель будет достигнута. Первая подцель выполняется при сопоставлении Person1 с peter. Теперь Лабораторная работа № 1 может перейти к следующей подцели:

player(Person2, 9).

Если опять сопоставить Person2 с peter, Пролог перейдет к третьей и заключительной подцели

Person1 <> Person2.

Так как Person1 и Person2 оба связаны со значением peter, третья подцель не выполняется. Из-за этого, Лабораторная работа № 1 делает откат к предыдущей подцели, и ищет другое решение второй подцели:

player(Person2, 9).

Эта подцель выполняется, сопоставляя Person2 с chris.

Теперь третья подцель:

Person1 <> Person2

возвращает положительный результат, так как peter и chris разные люди. Теперь, основная цель выполняется, создавая турнир между chris и peter. Однако так как Лабораторная работа № 1 должен найти все возможные решения, он делает откат к предыдущей цели, в надежде найти еще одно решение. Так как подцель

player(Person2, 9)

может также быть удовлетворена, сопоставляя Person2 со susan, Лабораторная работа № 1 пробует третью подцель еще раз. Она опять выполняется (так как peter и susan разные люди), поэтому найдено еще одно решение.

Пытаясь найти большее количество решений, Лабораторная работа № 1 еще раз делает откат ко второй подцели, но все решения для этой подцели были найдены. Поэтому теперь делается откат к первой подцели. Она может иметь и другое решение: Person1 сопоставим с chris. А решением второй подцели теперь оказывается сопоставление Person2 с peter, в итоге и третья подцель выполняется. Т.е. была найдена еще одна пара игроков для турнира: chris и peter.

Для поиска еще одного решения, Лабораторная работа № 1 опять делает откат ко второй подцели в правиле. Person2 связывается с chris, но в данном случае третья подцель не выполняется, так как Person1 и Person2 один и тот же человек, поэтому опять происходит откат ко второй подцели в поиске другого решения. Person2 теперь связывается со значением susan, и третья подцель выполняется, обеспечивая еще одну пару для турнира (chris против susan).

И опять пытаемся найти новое решение. Пролог делает откат ко второй подцели, но на сей раз безуспешно. Когда вторая подцель не выполнилась, происходит откат к первой подцели, на этот раз, связывая Person1 со susan. Пытаясь выполнять вторую подцель, Пролог сопоставляет Person2 с peter, и третья подцель возвращает положительный результат при данных Person1 и Person2. Найдена пятая пара игроков для турнира.

Делая опять откат ко второй подцели, Person2 связываем с chris. Найдено шестое решение.

Последнее решение, это и Person1, и Person2 сопоставить с susan. Так как третья подцель в данном случае не выполнится, Лабораторная работа № 1 делает откат ко второй подцели, но никаких новых решений не находится. Тогда Лабораторная работа № 1 делает откат к первой подцели, но опять нам это ничего не дает. Так как для данной цели больше решений не может быть найдено, программа заканчивается.

  1. Введите следующую составную цель:

player(Person1, 9),

player(Person2, 9),

Person1<> Person2.

  1. Пролог выдаст вам ответ (рис. 1):

Person1=peter, Person2=chris

Person1=peter, Person2=susan

Person1=chris, Person2=peter

Person1=chris, Person2=susan

Person1=susan, Person2=peter

Person1=susan, Person2=chris

6 Solutions

Р ис. 1. Вывод результата программы

  1. Рассмотрим пример и создадим новый проект.

Имеется база данных, содержащая следующие предикаты: отдыхает(имя, город), украина(город), россия(город), прибалтика(город). Составить правило, позволяющее определить, кто отдыхал в России. Проследить поиск решения задачи с помощью отладчика Visual Prolog и построить целевое дерево поиска с возвратом.

  1. З апустите среду Visual Prolog и создайте новый проект (Project | New Project), активизируется окно Application Expert (Эксперт приложения) (рис. 2).

Рис. 2. Создание нового проекта

  1. Определите имя проекта (Primer) и базовый каталог, куда будет сохранен проект (рис. 3).

Рис.3. Окно Application Expert

  1. Н а вкладке Target установите параметры и нажмите кнопку Create для создания проекта (рис. 4).

Рис. 4. Установки на вкладке Target окна Application Expert

  1. Откройте окно Compiler Options (Options | Project | Compiler Options).

  2. Откройте вкладку Warnings и установите опции компилятора для созданного проекта (рис. 5).

Рис. 5. Установки опций компилятора

Нажмите OK.

  1. В окне проекта выделите файл Пример.pro и откройте его для редактирования (двойной щелчок или кнопка Edit) (рис. 6).

Рис. 6. Окно проекта

  1. Файл с расширением *.pro содержит секции PREDICATES, CLAUSES, GOAL. Допишите необходимые определения так, чтобы получилась программа (рис. 7):

DOMAINS

имя, город = string

PREDICATES

отдыхает(имя, город)

украина(город)

россия(город)

прибалтика(город)

отдых_россия(имя)

CLAUSES

отдыхает(sasha, antalia).

отдыхает(anna, sochi).

отдыхает(dima, urmala).

отдыхает(oleg, kiev).

украина(kiev).

россия(sochi).

прибалтика(urmala).

отдых_россия(X):- отдыхает(X, Y), россия(Y).

GOAL

отдых_россия(X), write(X), nl.

Р ис. 7. Окно проекта

  1. Сохраните проект (Project | Save Project).

  2. Запустите его на исполнение (Project | Run, или клавиша <F9>, или кнопка <R>).

Результат выполнения программы:

anna

  1. Проследите поиск этого решения с помощью отладчика (Debugger) (рис. 8). Для этого:

  1. запустите отладчик (Project | Debug);

  2. в окне отладчика выберите команду View | Local Variables (для просмотра текущих значений переменных);

  3. нажимайте клавишу <F7> (или Run | Trace Into) для пошагового выполнения программы, текущие значения переменных отображаются в окне Variables For Current Clause.

Выноска 2 39

Рис. 8. Окно отладчика

Поиск решения можно представить следующим образом (рис. 9):

Полотно 37

решение: X= anna

Рис. 9. Целевое дерево поиска решения

Использование предиката fail

Лабораторная работа № 1 производит откат, когда какой-то запрос терпит неудачу. В некоторых ситуациях, необходимо вызвать откат для поиска всех решений. Лабораторная работа № 1 имеет специальный предикат fail, который служит как не выполнимая подцель, заставляющая вызывать откат. Эффект предиката fail соответствует эффекту сравнения чисел 2 и 3 или любой другой невозможной подцели.

  1. Рассмотрим следующий пример программы, иллюстрирующей использование предиката fail.

База данных содержит факты вида father(name, name). Создать проект, позволяющий определить, кто чей отец.

  1. Создайте новый проект и напишите нижеприведенный программный код.

DOMAINS

name = symbol

PREDICATES

father(name, name)

everybody

CLAUSES

father(“павел”, “петр”).

father(“петр”, “михаил”).

father(“петр”, “иван”).

everybody:- father(X, Y), write(X, “ - это отец”, Y, “a”), nl, fail.

GOAL

everybody.

Результат выполнения программы (рис. 10):

павел - это отец петра

петр - это отец михаила

петр - это отец ивана

Р ис. 10. Вывод программы

Если внутренняя цель полностью выполнится, то ничего не заставляет Лабораторная работа № 1 делать откат. Поэтому внутренний запрос father имеет только одно решение. Однако предикат everybody в программе использует fail для вызова отката и происходит поиск всех возможных решений.

Объект предиката everybody производит более корректный ответ. Предикат everybody использует откат для поиска всех решений father(X, Y), заставляя Пролог постоянно крутиться в теле правила everybody, пока не выполниться одна из предшествующих подцелей:

father(X, Y), write(X," is ",Y, "а"), nl, fail.

fail никогда не выполниться, поэтому Лабораторная работа № 1 вынужден постоянно делать откат. Когда используется откат, Пролог делает откат к последнему запросу, позволяющему находить множественные решения. Такой запрос называется недетерминированный. Недетерминированный запрос является противоположностью детерминированного запроса, который может иметь только одно решение.

Предикат write является детерминированным, поэтому Лабораторная работа № 1 должен делать откат к первой подцели в правиле.

Обратите внимание, что бесполезно размещать подцель после fail в теле правила. Так как предикат fail всегда не выполняется, то и стоящие за ним подцели никогда не будут выполнены.

  1. Создайте проект, реализующий железнодорожный справочник. В справочнике содержится следующая информация о каждом поезде: номер поезда, пункт назначения и время отправления.

  1. вывести всю информацию из справочника;

Решение:

DOMAINS

nom = integer

p, t = string

PREDICATES

poezd(nom, p, t)

CLAUSES

poezd(233, moskva, “12-30”).

poezd(257, moskva, “22-40”).

poezd(133, armavir, “10-20”).

poezd(353, armavir, “20-40”).

poezd(353, adler, “02-30”).

poezd(413, adler, “11-10”).

poezd(256, piter, “21-30”).

GOAL

write(“Расписание поездов”), nl,

write(“Номер Пункт прибытия Время отправления”), nl,

poezd(N, P, T), write(N, “ ”, P, “ ”, T), nl, fail.

Результат выполнения программы:

Расписание поездов

Номер Пункт прибытия Время отправления

233 moskva 12-30

257 moskva 22-40

133 armavir 10-20

353 armavir 20-40

353 adler 02-30

413 adler 11-10

256 piter 21-30

  1. организовать поиск поезда по пункту назначения;

Решение:

GOAL

write ("Пункт назначения:"), readln(P), nl,

write ("Номер Время отправления"), nl,

poezd(N, P, T), write(N, " ", T), nl, fail.

Результат выполнения программы:

Пункт назначения: armavir

Номер Время отправления

133 10-20

353 20-40

  1. вывести информацию о поездах, отправляющихся в заданный временной промежуток.

Решение:

GOAL

write(" Время отправления:"), nl,

write("c..."), readln(T1),

write("до..."), readln(T2), nl,

write("Номер Пункт назначения Время отправления"), nl,

poezd(N, P, T), T >= T1, T <= T2, write(N, " ", P, " ", T), nl, fail.

Результат выполнения программы:

Время отправления:

c...10-00

до...15-00

Номер Пункт назначения Время отправления

233 moskva 12-30

133 armavir 10-20

413 adler 11-10

20. Рассмотрим другой пример: имеется база данных, содержащая данные о спортсменах: имя и вид спорта. Определить возможные пары одного из спортсменов-теннисистов с другими теннисистами.

Решение:

DOMAINS

имя, вид_сп = string

PREDICATES

играет(имя, вид_сп)

спис_спортс

CLAUSES

играет("саша", теннис).

играет("аня", волейбол).

играет("олег", футбол).

играет("коля", теннис).

играет("саша", футбол).

играет("андрей", теннис).

спис_спортс:- играет(X,теннис), !, играет(Y, теннис),

X<>Y, write(X, "-", Y), nl, fail.

GOAL

write("Пары теннисистов"),nl,

спис_спортс.

Результат выполнения программы:

Пары теннисистов

саша-коля

саша-андрей

Использование предиката not

Есть одна вещь, на которую необходимо обращать внимание при использовании предиката not: он выполняется, если нельзя доказать правомерность подцели. Это приводит к ситуации, которая запрещает несвязанным переменным быть связанным в предикате not. Когда подцель со свободными переменными вызывается из not, Лабораторная работа № 1 возвращает сообщение об ошибках Free variables not allowed in 'not' or 'retractall' (Нельзя использовать свободные переменные в 'not' или в 'retractall'). Это происходит потому, что Пролог, чтобы связать свободные переменные в подцели, должен эту подцель объединить с некоторым другим предложением, и подцель должна быть выполнена. Правильный способ обрабатывать несвязанные переменные в пределах подцели not - использовать анонимные переменные.

Если Вы перепишите это так, чтобы подцель not стояла первой в теле правила, Вы получите сообщение о том, что свободные переменные не могут быть использованы в not.

Неправильное использование приведет к сообщению об ошибке или к ошибке в логике вашей программы.

  1. Следующий пример показывает правильный способ использования предиката not.

PREDICATES

nondeterm likes_shopping(symbol)

nondeterm has_credit_card(symbol, symbol)

bottomed_out(symbol, symbol)

CLAUSES

likes_shopping(Who):-

has_credit_card(Who, Card),

not(bottomed_out(Who, Card)),

write(Who, “ can shop with the ”, Card, “ credit card.\n”).

has_credit_card(chris, visa).

has_credit_card(chris, diners).

has_credit_card(joe, shell).

has_credit_card(sam, mastercard).

has_credit_card(sam, citibank).

bottomed_out(chris, diners).

bottomed_out(sam, mastercard).

bottomed_out(chris, visa).

  1. Введите следующую цель:

likes_shopping(Who).

Пролог ответит (рис. 11):

Рис. 11. Вывод результата программы