Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка_РЛП_4_форм.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
644.61 Кб
Скачать

3.8.Арифметика в языке пролог

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

:- op( 700, xfx, [=, is, <,<>, >, <=, >=]).

:- op( 500, yfx, [+, -] ).

:- op( 500, fx, [+, -] ).

:- op( 400, yfx, [*, /, div] ).

Пример 3.8.1. Программа вычисления наибольшего общего делителя.

Определение предиката:

нод(X,X,X).

нод(X,Y,Д):-Х<Y, Y1 is Y-X, нод(X,Y1,Д).

нод(X,Y,Д):-Y<X, нод(Y,X,Д).

Примеры применения:

?-нод(24,45,5)

No

?-нод(24,45,X)

X=3

Рассмотрим второе предложение этого примера.

нод(X,Y,Д):-Х<Y, Y1 is Y-X, нод(X,Y1,Д).

Пролог видит его в следующем представлении

нод(X,Y,Д):-<(Х,Y), is(Y1,-(Y,X)), нод(X,Y1,Д).

Из примера видно, что арифметические операции присутствуют в качестве функторов в структурах. Операции сравнения, «is» работают в Прологе как встроенные предикаты следующим образом:

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

  • если некоторые переменные в арифметическом выражении не имеют значений, то предикат заканчивает работу «неудачей» (данная цель считается не достигнутой);

  • первый аргумент предиката «is» (левая часть) может быть переменной, не имеющей значения, тогда после вычисления второго аргумента (правой части) происходит сопоставление аргументов (присваивание переменной значения вычисленного выражения);

  • если сопоставления заканчивается «неудачей», то предикат «is» также заканчивается «неудачей»;

  • если отношение сравнения не выполняется, то соответствующий предикат заканчивается «неудачей»;

  • в остальных случаях предикаты заканчивают работу «успешно».

Пример 3.8.2. Длина списка.

Определение предиката:

Вариант 1.

длина([],0).

длина([X|Y],N):- длина(Y,N1), N is N1+1.

Вариант 2 (неверный).

длина1([],0).

длина1([X|Y],N+1):- длина(Y,N).

Примеры применения:

?- длина([1,2,3], N)

N=3

?- длина1([1,2,3], N)

N=0+1+1+1

?- длина1([1,2,3], N), N1 is N

N=0+1+1+1

N1=3

3.9.Отсечение и отрицание в языке пролог

Рассмотренные возможности Пролога имеют определенные ограничения. Первое из них связано с использованием хорновских дизъюнктов, которые не обеспечивают логическую полноту. Проще говоря, логическая операция «конъюнкция» реализуется перечислением предикатов в правой части правила, а «дизъюнкция» - возможностью описания нескольких правил с общей левой частью. А как реализуется в Прологе логическое отрицание, необходимое для логической полноты? Для его реализации введены встроенные предикаты.

Особого внимания заслуживает предикат «отсечения» (обозначается как «!»).

Рассмотрим формальный пример программы на Прологе:

С:- Р, Q, R, !, S, Т, U.

С:- V.

А :- В, С, D.

?- А.

Здесь А, В, С, D, Р и т.д. предикаты. Отсечение повлияет на вычисление цели С следующим образом. Перебор будет возможен в списке целей Р, Q, R; однако, как только точка отсечения будет достигнута, все альтернативные решения для этого списка изымаются из рассмотрения. Альтернативное предложение «С :- V.» также не будет учитываться. Отсечение, будет "невидимо" из цели А в предложении «А :- В, С, D.». Однако варианты достижения цели С будут связаны с перебором в списке подцелей S, Т, U.

Предикат fail всегда заканчивает работу «неудачей».

С помощью этих двух предикатов можно реализовать логическое отрицание.

Пример 3.9.1. Предикат отрицания

Определение предиката:

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

not(Р).

Словесная интерпретация:

Если предикат P заканчивается успешно, то после «fail» и «!» not(Р) заканчивается «неудачей».

Если предикат P заканчивается «неудачей», то вторая альтернатива предиката not обеспечивает успешное окончание not(Р).

Многие реализации языка ПРОЛОГ имеют встроенный предикат отрицания, не связанный с отсечением.

Второе назначение отсечения связано с необходимостью оптимизировать вычисления. Рассмотрим еще один вариант описания предиката «принадлежит».

Пример 3.9.2. Проверка отношения принадлежности списку.

принадлежит_проверка(X, [X | Хвост ]) :-!.

принадлежит_проверка(X, [Голова | Хвост ]):-принадлежит_проверка (X, Хвост).

Этот предикат не имеет таких возможностей, как описанный в примере 3.7.1.(без отсечения) Его нельзя использовать для перебора всех элементов списка. Однако, если задача заключается лишь в проверке принадлежности элемента списку, предикат из примера 3.7.1. породит при этом много бесполезных шагов.

Упражнения 3.9.1.

Рассмотреть работу алгоритма пролог-интерпретатора с предикатами «принадлежит» и «принадлежит_проверка» при различных вопросах к системе.

Программа

принадлежит(X, [X | Хвост]).

принадлежит(X, [Голова | Хвост]):-принадлежит(X, Хвост).

принадлежит_проверка(X, [X | Хвост]) :-!.

принадлежит_проверка(X, [Голова | Хвост]):-принадлежит_проверка(X, Хвост).

пример(X, Y):- принадлежит(X, Y), X>10.

пример_проверка(X, Y):- принадлежит_проверка(X, Y), X>10.

Вопросы к системе

?- пример(1, [1,2,3,4])

?- пример_проверка(1, [1,2,3,4])

?- пример(1, [1,1,1,1])

?- пример_проверка(1, [1,1,1,1])

?- пример(X, [1,2,3,4])

?- пример_проверка(X, [1,2,3,4])