Рекурсия

Вычисление факториала:

.f(0)=1 f(n+1)=(n+1)*f(n)

.predikrtes fak(integer, real)

.clauses

fak(0,1):-!. /* 0!=1 */

fak(N, Fak):-

N>0, /*только для целых положит*/

N1=N-1,

.fak(N1,Fak1), /*опред.(n-1)! */

Fak=N*fak1. /*f(n)=n*f(n-1) */

Goal

.fak(2,X), write(X). /* 2! */

goal

X
(1) fak(2,X)

Fak
N
(2) fak(N,Fak)

(3) fak(2,Fak)

(4) N>0

N1=1
(5) N1=N-1

Fak1
(6) fak(N1,Fak1)

 
 


Fak
N
(7)fak(N,Fak)

N=1
(8) fak(1,Fak)

(9) N>0

N1=0
(10) N1=N-1

Fak1
(11) fak(N1,Fak1)

 
 


(12) fak(0,1)

 
 


Fak=1
Fak=1
(13) Fak=N*Fak1

           
 
   
 
   
Fak=1
 

 


Fak=2
(14) Fak=N*Fak1

 
 


X=2

(15).write(X)

 

2.7 Обработка списков

Список – это упорядоченная элементов, причем элементами могут быть любые термы, включая другие списки.

Пустой список- [ ]

Непустые списки имеют-голову и хвост. Они являются компонентами функтора, обозначаемого точкой ”.”.Например список из одного элемента а представляется так:

.(а,[])

где а-голова и []-хвост. Список элементов a,b, и c имеет вид:

.(а,.(b,.(c,[]))).

То есть, за элементом a следует b, который в свою очередь является головой списка .(b,.(c,[])).

Драгим видом записи списка будет:

._._._[].

На ТП такой список представляется так:

[a,b,c]

где a-голова, b,c-хвост списка, который и сам является списком.

Например, информация о некоторых семьях может выглядеть как предикат со следующей структурой:

.семья(фамилия, имя_отца, имя_матери, [имена детей] ).

Семья(Иванов,Иван,Людмила,[Антон,Наташа,Юрий] ).

В этом случае количество детей не имеет значение, а количество аргументов предиката семья всегда одинаково. Поэтому, если записать целевое утверждение:

семья(X,Y,Z,Дети).

То переменные конкретизируются так:

X=”Иванов” Y=”Иван” Z=”Людмила”

Дети=[“Антон”,”Наташа”,”Юрий”]

На ТП есть специальная форма представления списка

[X|Y].

Если такой спосок сопоставляется с другим списком, то X конкретизируется головой, а Y- хвостом того списка, например:

.семья(X,Y,Z,[Det1|Deti]),

то переменные конкретизируются так:

X=”Иванов” Y=”Иван” Z=”Людмила”

Det1=”Антон” Deti=[”Наташа”,”Юрий”].

 

Например, наити семью, где имеется ребенок с именем Алекс.

/* set femili */

trace

domains

detlist= person*

person= string

predicates

member(person,detlist)

semja(person,person,person,detlist)

clauses

member(X,[X|_]).

member(X,[_|Y]):-member(X,Y).

semja("Ivanov","Ivan","Ljda",["Anton","Nata","Jri"]).

semja("Sevs","Piter","Vera",[]).

semja("Pospelov","Serg","Ira",["Aleks","Tanj"]).

goal

makewindow(1,121,0,"",12,40,13,40),

semja(F,I1,I2,Det),member("Aleks",Det),

write("Aleks ",F),nl,

write("ОТЕЦ=",I1," МАТЬ=",I2).

 

 

При этом предикат member проверяет принадлежность элемента к списку:

Первый дизъюнкт предиката member означает, что искомый элемент находится в голове списка. Если это не так, то выбирается второй дизъюнкт, который отделяет хвост от головы списка и проверяет, находится ли искомый элемент в хвосту. Это происходит рекурсивно до тех пор, пока либо не найдено, что у остатка списка голова является искомым элементом (удача), либо не окажется, что после отделения хваста от головы остался пустой список([]), который уже не расщепляется на голову и хвост (неудача).