Merhaba arkadaşlar,

Uzun bir aradan sonra tekrar beraberiz. Bir önceki yazımda prolog programlama dilinin sintaks yapısından ve nasıl işlenildiğinden bahsetmiştik. Bu yazımda Prolog’un en önemli konusu olan rekürsif yapılarından bahsetmek istiyorum.

Öncelikle rekürsif tanımını verip devamında prologda nasıl çalıştıgından bahsedeceğiz daha sonra bol bol örnek çözüp ve yazının sonunda prologta dinamik programlamayla ilgili sürpriz bir örneğimiz olacaktır.

Prolog yordam çağırma yöntemiyle çalışır. Prolog yordamların tanımlamaları ve onların değerlendirilmesi ile oluşur.

Kendi kendisini doğrudan yada dolaylı yoldan çağıran fonksiyonlara özyinelemeli(recursive) diyoruz. Özyineleme bir problemi benzer şekilde olan daha küçük parçalalara bölünerek çözülmesini sağlayan bir tekniktir. Özyineleme dallanma algoritması kulanır.

Fonksiyon özyineli olarak her çağrışında yerel değişkenler ve parametreler için bellekte yer ayrılır. Özyineleme problemin çözümünü basitleştirelir ve genelikle kodu ksıadır ve kolayca anlaşılabilir.

Peki prologta bu nasıl oluyor? Prologta yapı çok basittir. Öncelikle özyineleme kuralı yazılır, ise ifadesi konulduktan sonra yuklemler listesi sıralanır. En sonda nokta ile bitirilir. Hemen ne demek istediğimi kaba kod şeklinde verelim.

  • <özyinelemeli kural> :-
  • <yüklemler listesi>,
  • <çıkış şartını ifade eden yüklem>,
  • <yüklemler listesi>,
  • <özyinelemeli kural> ,
  • <yüklemler listesi>.

Şimdi Özyineleme ile ilgili bazı örnekler çözelim.

Ata ilişkisini yine ata ilişkisini kulanarak (öz yineleme) tanımlayalım.

Tüm X ve Z ler için; X , Z’ nin atasıdır. Eger Y diye bir kişi varsa ve

(1) X, Y’nin ebeevyni ise ve

(2) Y, Z’nin ata ‘ sı ise

Bunu prologta şöyle ifade ederiz.

Ata(X,Z):- ebevyn(X,Y),

Ata(Y,Z).

şimdi başka başka bir örnekle konuyu daha iyi pekiştirelim

Elimizdeki bir listanin recursive le uzunluğunu bulmaya çalışalım

Mantıksal tanımlaması bu şekilde olur.

Liste_uzunlugu([1, 2, 3], Eleman_sayisi1).

Liste_uzunlugu([2, 3], Eleman_sayisi2).

Liste_uzunlugu([3], Eleman_sayisi3).

Liste_uzunlugu([], 0).

L3=0+1=1

L2=L3+1=2

L1=L2+1=3

boyut([],0).

boyut([H|T],N):-

boyut(T,N1),

N is N1+1.

İlk çalıştırdıgınızda programın çalışmasına engel olmamakla beraber şöyle bir uyarı mesajı verecektir

Singleton variables: [H]

Nedeni ise H bir tekil değişken olmasıdır bunu önlemek için H’ ın yerine bir anonim degişken(_) kulanabiliriz 2.satırdaki kodumuzu şu şekilde düzeltim tekrar çalıştırdığımızda,

boyut([_|T],N):-

boyut([],0).

boyut([_|T],N):-

boyut(T,N1),

N is N1+1.

Şimdi listemizi girelim ve cevap isteyelim.

1 ?- boyut([1,2,3,4],X).

X = 4.

2?- boyut([1,2,3,4,a,c],X).

X = 6.

3?- boyut([S,ü,l,e,y,m,a,n],X).

X = 8 // görüldügü gibi 3 farklı liste girdik ve üçünde de listenin uzunluğunu bize döndürdü

Üssel fonksiyon üs(X,Y,Z) X^Y=Z

üs(X,1,X).

üs(X,Y,Z):-

Y>1,

G is Y-1,

üs(X,G,T),

Z=X*T.

Kuralarımızı yazdıktan sonra sorumuzu yazabiliriz

?- üs(2,4,X).

X=16. (cevap)

Şeklinde özyineleme (iç içe) bir yapı dönderecek X = 2* (2* (2*2))

Burda G Y nin her sefer azalan degerini tutan bir ara değişken

T ise ara çarpımları tutuyor

Recursive deyip de faktöriyel çözmemek olmaz!

faktoriyel(0,1).

faktoriyel(A,B):- A>0,

C is A-1,

faktoriyel(C,D),

B is A*D.

Yazdıktan sonra 6 faktoriyelin sonucunu isteyelim

?- faktoriyel(6,X).

X = 720

Prolog la 100 bin faktoriyeli 2.10 saniyede hesaplanıldı….

Prolog yorumlayıcı tabanlı bir dil olduğundan derlenme için ayrıca zaman harcamaz bundan dolayı prolog zaman açısından buyuk bir kazanç sağlıyor.

Bu yazımız çok uzadığı için fibonnaci örneği ve dinamik programlamayı bir sonraki makalede yazacağım.

Bir sonraki yazımda buluşmak dileğiyle, esen kalın.