Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник_Final.doc
Скачиваний:
59
Добавлен:
09.11.2019
Размер:
10.39 Mб
Скачать

3.5. Предикаты

Системные предикаты

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

        • предикаты типа;

  • арифметические и логические предикаты;

  • предикаты ввода-вывода;

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

  • металогические предикаты (работа с термами, классификация термов);

  • предикаты управления и связи с операционной системой;

  • предикаты отладки программы.

Предикаты типа

Предикаты типа позволяют задать новую переменную определенного типа, а также проверить принадлежность переменной к тому или иному типу, например:

integer (C) – задает переменную C целого типа;

real (C) – задает переменную C вещественного типа;

char (C) – задает переменную C символьного типа;

symbol (C) – задает переменную C символьного типа;

string (S) – задает переменную строкового типа;

atom (A) – цель истинна, если терм A является атомом;

atomic (A) – цель истинна, если терм A является атомом или целым числом;

var (D) – цель истинна, если терм D является переменной;

nonvar (D) – цель истинна, если терм D не является переменной;

Арифметические предикаты

В Пролог-программе справедливы и используются все виды арифметических операций:

+ − сложение;

- − вычитание;

* − умножение;

/ − деление;

exp − возведение в степень.

Кроме этого имеются другие встроенные математические операции:

mod − модуль, остаток от целочисленного деления;

div − частное от деления;

sin − синус;

cos − косинус;

ln − натуральный логарифм.

Предикат унификации

Термин унификация [лат. unio − единство + facere − делать] − означает приведение чего-либо к единой норме, форме, единообразию. Унификация в программе на языке Пролог – это операция приведения к единому значению. Следует особо отметить, что предикат «=» не является оператором присваивания, хотя и может выполнять его функцию в частном случае.

Пример. Унификация, как присваивание значения

Программа вычисления факториала:

predicates

factorial (integer, real)

factorial (integer, real, integer, real)

goal

factorial (5, X),

write ("X = ", X).

clauses

factorial (Fact, N) :- factorial (Fact, N, 1, 1).

factorial (Fact, N, Fact, N) :- !.

factorial (Fact, N, P, I) :-

NewP = P + 1, /* унификация */

NewI = NewP * I, /* унификация */

factorial (Fact, N, NewP, NewI).

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

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

Пример. Унификация выражения с переменной

Дано выражение: R = exp (X * ln (Y)).

predicates

power (integer, integer)

goal

readint (X),

readint (Y),

power (X, Y).

clauses

power (X, Y) :-

R = exp (Y * ln (X)), /* операция унификации */

write(X, "^", Y, "=", R), nl.

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

Пример. Унификация структуры

Дано выражение:

? студент (Петров, 4, 21) = студент (X, Y, Z),

где X= Петров, Y= 4, Z=21.

domains

summa = real

proizv = real

itog = real

predicates

summa_chisel (real, real, summa)

proizv_chisel (real, real, proizv)

itog_chisel (summa, proizv, itog)

goal

makewindow (1, 10, 2, "Сумма и произведение", 0, 0, 25, 80),

write ("Введите первое число:\n A = "),

readreal (A),

write ("Введите второе число:\n B = "),

readreal (B),

write ("Сумма:\n C = A + B = "),

summa_chisel (A, B, C), write (C),

write ("\nПроизведение:\n D = A * B= "),

proizv_chisel (A, B, D), write (D),

write ("\nИтог:\n E = C + D = "),

itog_chisel (C, D, E), write (E).

clauses

summa_chisel (A, B, C) :- C = A + B. /* операция унификации */

proizv_chisel (A, B, D) :- D = A * B. /* операция унификации */

itog_chisel (C, D, E) :- E = C + D. /* операция унификации */

Одной из фаз процесса доказательства целевого утверждения является унификация его аргументов с аргументами утверждений базы знаний. Рассмотрим, как работает предикат унификации в том случае, когда аргументами цели являются списки [22].

Введем понятие шаблона (образца) списка, как формы описания множества (семейства) списков, обладающих определенными свойствами.

Например:

    • шаблон списка [Х | Y] описывает любой произвольный список, состоящий не менее чем из одного элемента;

    • шаблон [Х1, Х2 | Y] − список, состоящий не менее чем из двух элементов;

    • аналогично [Х1, Х2, Х3 | Y] − список, содержащий не менее трех элементов; а шаблон в виде переменной Z − любой список, в том числе и пустой.

Шаблон может содержать как переменные, так и константы. Например, шаблон [b | Z] задает любой список, первым элементом которого является элемент b.

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

[Х1, Х2 | Т], [a], [Х1, Х2, Х3 | Z], [1, 2] и т.д.

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

Примеры: шаблон [[X, Y] | Z] задает список, начинающийся с подсписка из двух элементов; при сопоставлении его со списком [[a, b], c] унификация проходит успешно и переменные принимают следующие значения: Х = a, = b, = [c].

Шаблоны [X, Y | Z] и [[a, b] | T] при сопоставлении дают общее решение − новый шаблон [[a, b], Y | Z]; образец [[X | Y] | Z] описывает любой список, начинающийся с подсписка, в котором есть, по крайней мере, один элемент − элемент Х. Он соответствует, например, таким спискам:

[[a]] при = a, = [ ], = [ ];

[[a, b], c] при = a, = [b], Z = [c].

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

['бал', Y, Y] [X, X, 'цех'],

где сопоставление показывает, что элементы обоих списков должны быть одинаковы, однако 'бал' не равно 'цех' [22].

Предикаты отношений

В Пролог-программе (версия Турбо-Пролог 2.0) используются следующие предикаты отношений [25]:

< − меньше;

> − больше;

<= − меньше или равно;

>= − больше или равно;

= − равно;

>< или <> − не равно.

Запись отношений также имеет инфиксную форму − «выражение (знак отношения) выражение» − и является термом, т.е. синтаксически правильной конструкцией языка Пролог. Терм считается синтаксически неверным, если в одной из частей (правой или левой от знака отношения) не будет стоять выражение, или в одной из частей будет только константа или атом. Интерпретатор вычисляет выражение в правой части, а затем − в левой. После этого выражения сравниваются с учетом знака отношения.

Предикаты ввода-вывода

Предикат ввода read используется в Пролог-программе в следующих нотациях:

readln (var) – ввод строковой переменной;

readint (var) – ввод целой переменной;

readreal (var) – ввод вещественной переменной;

readchar (var) – ввод символьной переменной,

При работе предиката read в Пролог-программе выполняется конкретизация переменной X с термом из текущего входного потока (значением, вводимым пользователем в режиме диалога в клавиатуры или посредством формы, отображаемой на экране монитора, либо – из внешнего файла с данными или из БД). Если значение X будет недопустимым, то конкретизация не произойдет, программа терпит неуспех, а результат может быть непредсказуем.

Предикат вывода в Пролог-программе имеет следующую форму:

write (<аргумент_1>, ... , <аргумент_ N>).

Он выводит на текущее устройство (по умолчанию − экран дисплея) значения аргументов <аргумент_1>, ... , <аргумент_ N>, которые могут быть константами или переменными с заранее присвоенными значениями.

В предикате write можно использовать символы, начинающиеся со знака «\» и имеющие специальные значения:

\k – символы, имеющие ASCII код числа k;

\n – возврат каретки и перевод строки;

\t – табуляция.

Предикат форматного вывода:

writef (format, arg1, ... , argN)

подобен write, но осуществляет форматированный вывод в соответствии с параметром format, который имеет вид

%p,

где символ «p» может принимать следующие значения, соответствующие определенному формату выводимого числа:

d – нормальное десятичное число (символы и целые числа);

u –целое без знака;

s – строка (атомы или строки);

c – символ (цифры или буквы);

g – вещественное число в коротком формате;

e – вещественное число в экспоненциальном представлении;

f – вещественное число в десятичном представлении (по умолчанию);

x – шестнадцатеричное число (символы и целые числа).

К предикатам ввода-вывода также относятся предикаты окна.

Предикат открытия окна имеет следующий формат:

makewindow (A, B, C, D, E, F, G, L),

где A − номер открытого окна;

B − число, определяющее цвет фона в окне;

C − (число) атрибут рамки окна;

D − заголовок открытого окна (строка);

E − номер ряда (строки), с которого начинается окно;

F − номер столбца начала окна;

G − высота окна;

L − ширина окна.

Предикат закрытия окна имеет вид:

removewindow (W, Z),

где, W – номер окна;

Z – число 0 или 1, задающее обновление экрана после закрытия окна (по умолчанию 0).

Пример.

predicates

run (char)

goal

run (X).

clauses

run (X) :- makewindow (1, 2, 3, "Привет", 0, 0, 25, 80),

write ("Здравствуйте!"),

readchar (X),

removewindow.

Предикаты управления работой программы

В процессе работы Пролог-программы осуществляется:

  1. нахождение правила для текущей цели (подцели);

  2. конкретизация переменных данного правила по аксиомам;

  3. возврат, если сопоставимых аксиом нет;

  4. ветвление программы;

  5. означивание переменных и дальнейшее сопоставление правил с аксиомами.

Предикат цикла

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

predicates

nondeterm repeat

clauses

repeat :- repeat.

repeat.

Пример.

Программа переводит введенные символы в верхний регистр, выход из цикла осуществляется по нажатию клавиши «Enter»:

predicates

nondeterm repeat

typewrite

goal

makewindow (1, 2, 3, "Result", 0, 0, 20, 60),

typewrite,

removewindow.

clauses

repeat.

repeat :- repeat.

typewrite :-

repeat,

readchar (C),

upper_lower (C1,C), /* перевод в верхний регистр */

write ("\n", "C = ", C, " C1 = ", C1),

char_int (C1,13). /* выход из цикла по клавише Enter */

Предикаты отсечения

Для реализации ветвления программы используются два предиката отсечений – fail и cut.

Предикат cut, чаще обозначаемый в программе знаком «!», предназначен для исключения возможного перебора всех вариантов решений.

Пример.

Программа прекращает ввод символов с экрана при нажатии клавиши «Enter»:

predicates

typewrite (char)

goal

makewindow (1, 2, 3, "Entering", 0, 0, 25, 80),

readchar (C),

typewrite (C).

clauses

typewrite ('\13') :- !.

typewrite (C) :-

write (C),

readchar (C1),

typewrite (C1).

Если предикат repeat предназначен для успешного завершения цели, то предикат fail определяет неуспех. Предикат fail предназначен для вывода всех возможных решений цели, имеющихся в БД, и работает следующим образом. Если он встречается в программе, то текущая цель становится неразрешимой. Очистка всех переменных и доказательства проводится заново, исходя из последовательности аксиом, заданных в БД (поэтому важно, в каком порядке заданы аксиомы и правила).