Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ФиЛП_материалы / Материалы / Prolog / ПособиеПролог.doc
Скачиваний:
55
Добавлен:
01.06.2015
Размер:
449.02 Кб
Скачать

4. Управление процессом доказательства правил

4.1. Искусственный откат

Как уже неоднократно упоминалось, традиционный Пролог выдает все возможные решения, а VIP – одно. Можно ли в последнем случае получить множество решений? Да, если применить искусственный откат.

Искусственный откат организуется системным предикатом fail, который всегда ложен. Обычно он добавляется к телу правила, сформулированного для достижения цели программы, в качестве последней подцели. В этом случае переход к fail при доказательстве правила означает, что объявленная цель достигнута при каком-то наборе переменных. Так как fail не может быть доказан, то происходит откат на предыдущую подцель и производится ее пересогласование. Если оно имеет успех, то получается еще одно решение с другими значенями переменных, в случае неудачи – пересогласование предыдущей и т.д. Пересогласования продолжаются до тех пор, пока не будут исчерпаны все возможные варианты сочетаний значений переменных. Заключительный откат приводит к выходу из правила с объявлением заголовка правила недоказанным. Таким образом, цель, одной из подцелей которой является fail, всегда неуспешна, несмотря на то, что могут быть получены все возможные решения достижения задекларированной цели.

Рассмотрим применение fail на следующем примере. В базе данных некоторого торгового предприятия сведения об имеющихся автомобилях составлены по следующему шаблону:

авто(марка, цвет, цена, год_выпуска).

Запрос к базе данных о цене и годе выпуска автомобиля должен или дать сведения о них или сообщить об их отсутствии. Программа имеет следующий вид.

DOMAINS

марка=string

цвет=symbol

цена=integer

год=integer

PREDICATES

авто(марка,цвет,цена, год)

nondeterm поиск(цена, год)

nondeterm run

CLAUSES

авто("Accent",red,330000, 2002).

авто("Ford Focus",green,480000,2003).

авто("Волга 3110",green,180000, 2002).

авто("ВАЗ 2199",blue,220000, 2002).

авто("ВАЗ 2110",red,240000,2003).

авто("Sonata",white,520000, 2005).

run:-write(" Критерии для поиска"),nl,

write("Введите цену - "),readint(Цена),

write("Введите год выпуска - "),readint(Год),

поиск(Цена, Год).

поиск (Цена, Год):- write("Предлагаемые вариан

ты"), авто(Марка,Цвет,Цена,Год),nl,

write(Марка), write(" "),write(Цвет),nl, fail.

поиск(Цена, Год):- not(авто(_, _, Цена, Год)),

write("Поиск завершен"), nl, write("Такого авто

мобилянет"),readchar(_).

GOAL

run.

Искусственный откат гораздо чаще применяется в VIP, чем в традиционном Прологе. Отметим, что наряду с fail в Прологе существует предикат true, который всегда успешен.

4.2. Отсечение

Системный предикат "!" или «cut» , называемый отсечением, используется для отбрасывания вычислений, которые, как считает программист, не могут привести к искомому решению или являются избыточными.

Предположим, что имеется следующая процедура из двух правил с отсечением:

c:-p, q, r, !, s, t.

c:-v.

Правила отсечения следующие:

- до отсечения, т.е. вплоть до цели r, доказательство подцелей p, q, r производится в обычном режиме с сопоставлением и откатом;

- если отсечение пройдено, т.е. доказывается подцель s, то в случае неуспешного исхода запрещается откат с подцели s на подцель r; значения переменных, полученные до отсечения, «замораживаются»;

- если подцель s доказана, то при доказательстве t возможен откат на s и пересогласование последней; откат с s на r по-прежнему запрещен;

- если отсечение пройдено, то при любом исходе доказательств целей справа от отсечения нижележащие правила с тем же заголовком не рассматриваются.

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

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

Рассмотрим 2 случая применения отсечения в VIP.

1. Предотвращение возврата к предыдущей подцели.

PREDICATES

выбрать_авто(symbol,symbol)

авто(symbol,symbol,integer)

цвет(symbol,symbol)

CLAUSES

авто(ford, зеленый, 25000).

авто(nissan, черный, 24000).

авто(honda, бежевый, 26000).

авто(honda, красный, 24000).

цвет (бежевый, приятный).

выбрать_авто (Модель, Цвет):-

авто(Модель, Цвет, Цена) ,

цвет(Цвет,приятный),!, Цена < 25000.

GOAL

выбрать_авто (honda, Y) .

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

2. Предотвращение перехода к нижележащему одноименному правилу.

Запишем программу, которая работает по типу оператора switch в С: в зависимости от значения аргумента предиката r(X) обеспечивает выполнение одного из правил r(1), r(2), r(3) или выводит сообщение, что указанное значение X не соответствует имеющимся вариантам.

PREDICATES

r(integer)

a

b

c

CLAUSES

a:-write(“A”),nl.

b:- write(“B”),nl.

c:-write(“C”),nl.

r(1):- !,a,b,c.

r(2):- !,a,b.

r(3):-!,a.

r(_):-write(“Такого варианта нет”).

GOAL

r(2).

Предположим, что отсечений в программе нет. Тогда, в случае, если подцель «a» или «b» в правиле r (2) не будут по каким-либо причинам доказаны, то произойдет переход к r ( _ ), что противоречит алгоритму работы switch. Наличие отсечения гарантирует передачу управления на предикат, расположенный после r ( _ ) ( в нашем случае это завершение программы).

Отсечение используется в рекурсивных процедурах при программировании на традиционном Прологе для того, чтобы избежать получения нескольких вариантов решения. Например, если в процедуру «предок», приведенную в подразд. 2.2, ввести отсечение в терминальный предикат

предок(X, W) : - отец (X, W),!.

предок(X, W) : - отец(X, Y), предок (Y, W).,

то решение будет одно, а не пять, как при отсутствии отсечения.

Используя отсечение, запишем пользовательское определение предиката not:

not( P) :-Р, !, fail.

not(P):-true.

Следует заметить, что not не полностью соот­ветствует отрицанию в математической логике. Действительно, цель P может быть неуспешной не только в том случае, когда она ложная, но и в том случае, когда соответствующего предиката в БЗ не существует. Эта разница может породить неожиданности в толковании полученных результатов.

Как правило, отсечение увеличивает эффективность программы. Вместе с тем при его применении возможны потери решения и даже изменение декларативного смысла программы. Для иллюстрации такого случая приведем следующий пример.

Декларативный смысл процедуры

p : - a, b.

p : - c.

cледующий: ‘p’ истинно тогда, когда истинны одновременно ‘а’ и ‘b’ или ‘с’. Введем в процедуру отсечение

p : - a, !, b.

p : - c.

Декларативный смысл изменился: p истинно тогда, когда истинны одновременно ‘а’ и ‘b’ или not(а) и ‘с’.

Возвращение к первоначальному декларативному смыслу происходит при перестановке правил:

p: - c.

p : - a, !, b.

Соседние файлы в папке Prolog