Логическое программирование

       

Структуры


В соответствии с теорией предикатов первого порядка единственная структура данных в логических программах - термы. Определение термов индуктивно. Константы и переменные являются термами. Кроме того, термами являются составные термы, или структуры. Составной терм содержит функтор (называемый главным функтором терма) и последовательность из одного или более аргументов, являющихся термами. Функтор

задается своим функциональным именем, которое суть атом, и своей арностью

(местностью), или числом аргументов. Синтаксически составные термы имеют вид f(t1,t2,...,tn), где f - имя n-арного функтора, а ti - аргументы. Геометрически мы можем рассматривать термы как деревья, где для составного терма корнем является главный функтор терма, а поддеревьями - его аргументы.

Поскольку предикаты синтаксически выглядят так же, как составные термы (роль функтора играет предикатный символ), то, следовательно, программы и данные в Прологе имеют одинаковую форму (как в Лиспе).

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

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

Примеры:

?- X is *(+(5,4),+(5,8)).

X = 117

Yes

?- X = *(+(5,4),+(5,8)).

X = (5 + 4) * (5 + 8)

Yes



Структуры используются в Прологе для конструирования сложных типов данных. Например, для представления даты естественно использовать терм вида  ‘дата’(1,’май’,1998).

 

Проверка типа терма

Для проверки типа терма используются встроенные предикаты.

var(+Term) - свободная переменная

nonvar(+Term) - несвободная (конкретизированная) переменная

integer(+Term) - целое число

float(+Term) - вещественное число


number(+Term) - целое или вещественное число

atom(+Term) - атом

atomic(+Term) - атом или число

ground(+Term) -терм не содержит свободных переменных

Если не var(X) и не atomic(X), то X - структура.

 

Рекурсивные структуры

Рассмотрим использование рекурсивных структур при представлении простых электрических цепей. Пусть цепи содержат только резисторы, соединенные последовательно или параллельно.

Цепь, состоящую из одного резистора, будем представлять числом - номиналом резистора. Два резистора R1 и R2, соединенные последовательно, обозначим термом succ(R1,R2), а параллельно - термом para(R1,R2). Используя эти обозначения рекурсивно, мы можем определить произвольные цепи, состоящие только из последовательно и параллельно соединенных сопротивлений. Например, цепь из 4 резисторов:

para(1.0,succ(para(2.0,3.0),4.0)).

Упрощение цепей

simple(X,X):-

        number(X).

simple(succ(X,Y),Z):-

        simple(X,R1),

        simple(Y,R2),

        Z is R1+R2.

simple(para(X,Y),Z):-

        simple(X,R1),

        simple(Y,R2),

        Z is (R1*R2)/(R1+R2).

?- simple(para(1.0,succ(para(2.0,3.0),4.0)),X).

X = 0.838710

Yes

Бинарные деревья

Бинарные деревья задаются с помощью тернарного функтора tree(Left,Root,Right), где Root - элемент, находящийся в вершине, а Left и Right - соответственно левое и правое поддерево. Пустое дерево изображается атомом nil. Следующий терм является примером более сложного дерева tree(nil, 5, tree(nil, 6, tree(tree(nil, 8, nil), 10, nil))).

% tree_member(+Element,+Tree)

% Отношение выполнено, если элемент является одной из вершин дерева

tree_member(X,tree(_,X,_)).

tree_member(X,tree(Left,_,_)):-

                     tree_member(X,Left).

tree_member(X,tree(_,_,Right)):-

                     tree_member(X,Right).


Содержание раздела