Bu yazının amacı, PROLOG diline giriş yapmak ve basit bazı yapay zeka problemlerinin PROLOG dilinde nasıl kodlanarak cozulduğunu gostermektir. Kurulum ve calıştırma: Bu yazı kapsamında SWI-PROLOG programı kullanılacaktır. Programı, www.swi-prolog.org adresinden temin etmek mumkundur. Yazı kapsamında MAC OSX uzerinde ornekler calıştırılarak gosterilecektir ancak kurulum ve sonrasında başarılı bir calıştırma yapılabiliyorsa hangi işletim sisteminde olduğunuzun bir onemi yoktur, butun sistemlerde aynı PROLOG komutları calışır. Siteden indirilip kurulum yapıldıktan sonra, $ /opt/local/bin/swipl Dizini altında bulunan swipl komutu calıştırılarak, PROLOG komut satırı acılabilir. Program calıştırıldığında, aşağıdakine benzer bir komut satırı ile komut girilmesini bekleyecektir: ?- _ Yardım İlk ve en onemli komutumuz olan yardım komutu ile başlayabiliriz. ?- help(help). Bu komut, X11 ekranında, yardım dokumanını goruntuleyecektir. Basitce herhangi bir komut hakkında bilgi alınmak istendiğinde bu komutu help fonksiyonuna parametre olarak vermek yeterlidir. Yukarıdaki kullanımda help komutunun kendisi icin yardım alınmıştır. Cıkış Prolog komut satırından cıkmak icin ?- halt. Yazılması yeterlidir. Bu komut programı sonlandıracaktır. Basit Kaziyeler Aşağıdaki komutları PROLOG uzerinde calıştıralım ve ardından burada yapılan işlemleri yorumlayalım. Sistemimizde kayıtlı olan bir dosyayı program tarafından acıp calıştırılır bir şekilde yuklemek icin dosya ismi koşeli parantezler icerisinde verilmelidir: ?- [‘ilkdosya.pl’]. Yukarıda, bilgisayarımızda bulunan “ilkdosya.pl” isimli dosyayı sisteme tanıtarak yukledik. Bu dosyada bulunan tanımlar da otomatik olarak yuklenmiş ve sorgulanmaya / calışmaya hazır hale getirilmiş olacaktır. Ayrıca bu dosyada bulunan genel hatalar, yukleme sırasında ekrana basılır. PROLOG ile Faktoriyel Kodu PROLOG dili, yapısal olarak ozyineli (recursive) bir yapıdadır ve dongulerin yerine ozyineli fonksiyon (recursive function) kullanılması gerekir. Bu kullanımı goreceğimiz en basit uygulamalardan birisi olan faktoriyel kodunu yazıp kodlamaya calışalım. Herhangi bir editor acılarak (ben tercihen vi kullanıyorum, siz de istediğiniz bir editor ile dosyayı acıp iceriğini ) aşağıdaki şekilde yazabilirsiniz: factorial(0,1). factorial(A,B) :- A > 0, C is A-1, factorial(C,D), B is A*D. Ardından aşağıdaki şekilde dosyamızı sisteme yukleyelim: ?- [‘ilkdosya.pl’]. % ilkdosya.pl compiled 0.00 sec, 732 bytes true. Komut satırında dosyamızın yuklendiği ve yukleme suresi ve dosya boyutu gosterilmektedir. Son satırda yer alan true bilgisine kadar bir hata bulunmamış olması, dosyamızda bir hata olmadığını gosterir. Şimdi artık ilk fonksiyonumuzu kullanmaya başlayabiliriz. ?- factorial(5,X). X = 120 ; false. Komut satırında, factorial(5,X) komutu verilerek, 5! Değerinin X değişkenine dondurulmesi istenmiştir. Burada oğrenilen birkac onemli noktayı belirtelim. Birincisi X ile gosterilen değer bir değişkendir ve PROLOG dunyasında buna unbounded variable (bağlanmamış değişken) ismi verilir. Basitce Prolog kodlarındaki butun buyuk harf ile başlayan ifadeler birer değişkendir ve ayrıca bir değişken tanımı yapılmaz. İkinci bir nokta, Prolog dilinde kod yazılırken girilen her satır bir emirdir ( declaration) ve yapısal olarak Prolog dili, haber mantığını (predicate calculus) barındırır. Buna gore yuklu olan dosyada bulunan komutlar yukarıdan aşağıya doğru calıştırılırken ustte bulunan satır, alttakine gore oncelikli olur ve aynı zamanda birden fazla satırda emirin tanımlanması durumunda, sırasıyla bu emirler işlenir. Orneğin yukarıdaki kodda, ilk satırda bulunan factorial (0,1). İfadesi, 0! = 1 anlamındadır ve bir şekilde birisi bize sıfır faktoriyeli sorarsa, ikinci değer olarak 1 sonucunu dondurmeyi gerektirir. İkinci satırdan sonra başlayan tanımda ise, sırasıyla A>0 kontrolu yapılmış, ardından C değişkenine değer olarak A-1 değeri konmuş ve yeni bulunan C değerinin faktoriyeli hesaplanarak, B sonucuna hesaplanan bu C faktoriyel değeri ile A’nın carpımı eklenmiştir. Yukarıdaki şekilde kodumuzu ilkdosya.pl dosyasına yazıp kaydettikten sonra prolog komut satırında dosyamızı yukleyip calıştırabiliriz: Yukarıda gorulduğu uzere faktoriyel kodumuz calışmış ve sonucu doğru şekilde bulmuştur. Kodun calışmasını takip etmek icin trace komutu kullanılabilir. Basitce komut satırında: trace. Yazıldıktan sonra calışmaya başlar ve bu calışmadan sonra cağrılan fonksiyonların detayları ekrana basılır: Gorulduğu uzere factorial fonksiyonumuzun her adımı ekrana basılmıştır. Hanoi Kuleleri (Towers of Hanoi) İkinci bir uygulama olarak cok klasik bilgisayar bilimleri problemlerinden olan Hanoi Kulelerini ( tower of hanoi ) kodlamaya calışalım. Oyunun kuralı gayet basit. Başlangıcta bir cubukta dizili olan butun diskler her adımda tek bir disk hareket ettirerek diğer iki cubuktan birisine taşınacaktır. Bu taşıma işlemleri sırasında buyuk bir disk, kucuk olan bir diskin uzerine gelmeyecektir. Ayrıca oyunun internetten oynan bir denemesi icin daha once hazırladığım aşağıdaki odev sayfasına bakabilirsiniz: http://www.sadievrenseker.com/c/odev5.html Problemin cozumunde kullanacağımız kod aşağıdaki şekildedir: SADIs-MacBook-Airrolog sadievrenseker$ vi hanoi.pl oyna(1,X,Y,_) :- write(X), write(‘ en ustteki diskini ‘), write(Y), write(‘ oynat ‘), nl. oyna(N,X,Y,Z) :- N>1, M is N-1, oyna(M,X,Z,Y), oyna(1,X,Y,_), oyna(M,Z,Y,X). Kod orneği yukarıda verilmiştir. Kodumuzun calışmasını gorup ardından nasıl calıştığını acıklamaya gecebiliriz. ?- oyna(4,a,b,c). a en ustteki diskini c oynat a en ustteki diskini b oynat c en ustteki diskini b oynat a en ustteki diskini c oynat b en ustteki diskini a oynat b en ustteki diskini c oynat a en ustteki diskini c oynat a en ustteki diskini b oynat c en ustteki diskini b oynat c en ustteki diskini a oynat b en ustteki diskini a oynat c en ustteki diskini b oynat a en ustteki diskini c oynat a en ustteki diskini b oynat c en ustteki diskini b oynat true . ?- Yukarıdaki calışmadan da gorulduğu uzere ilk baştaki 4 diskin dizili olduğu a cubuğundan butun diskler sırasıyla b cubuğuna taşınmıştır. Kodumuz, doğru sıra ile oynama yaklaşımı ile kodlanmıştır. Hanoi kulelerinin farklı cozumleri bulunur. Orneğin geri izleme algoritması (backtracking) kullanarak kaba kuvvetle (brute force) butun ihtimallerin denendiği ve başarısızlık olması halinde en son iyi duruma geri donen yaklaşımları kodlamak da mumkundur. Bizim kodlamamızda ise her seferinde doğru cubuktan doğru diskin oynatılması esası kullanılmıştı. Bu yuzden hic geri oynama veya yapılan hamleden vaz gecme olmamıştır. Bu oynama esasını daha iyi anlatabilmek icin daha ufak bir ornek uzerinden calışmayı gosterelim : ?- oyna(2,a,b,c). a en ustteki diskini c oynat a en ustteki diskini b oynat c en ustteki diskini b oynat true Gorulduğu uzere iki disklik bir dizilimde, c cubuğu gecici olarak kullanılmakta, esas buyuk diskin b cubuğuna oynanması sırasında, kucuk diskleri depolamak icin kullanılmaktadır. Bu durum disk sayısı artsa da değişmez. En buyuk diskin a cubuğundan b cubuğuna oynanması sırasında, diğer butun kucuk diskleri depolamak icin c cubuğunu kullanırız. Buradan anlaşılacağı uzere ikinci buyuk diskin c cubuğuna oynaması gerekir. Bunun icin de b cubuğunu gecici depolama icin kullanırız. Bu yaklaşım en buyuk diskten en kucuğune kadar aynı mantıkla işleyerek devam eder. 8 Vezir Problemi (8 Queens Problem) Yeni bir problem olarak klasik sorulardan birisi olan 8 vezir problemini ( eight queens problem) ele alalım. Problem basitce bir satranc tahtasına 8 veziri, birbirini yemeden nasıl yerleştireceğimizdir. Problemin cozumu olan PROLOG kodu aşağıda verilmiştir. perm([X|Y],Z) :- perm(Y,W), birinial(X,Z,W). perm([],[]). birinial(X,[X|R],R). birinial(X,[F|R],[F|S]) :- birinial(X,R,S). cozum(P) :- perm([1,2,3,4,5,6,7,8],P), birlestir([1,2,3,4,5,6,7,8],P,S,D), hepsifarkli(S), hepsifarkli(D). birlestir([X1|X],[Y1|Y],[S1|S],[D1|D]) :- S1 is X1 +Y1, D1 is X1 – Y1, birlestir(X,Y,S,D). birlestir([],[],[],[]). hepsifarkli([X|Y]) :- +member(X,Y), hepsifarkli(Y). hepsifarkli([X]). Kodun calışan orneği aşağıdaki şekildedir: ?- cozum(P). P = [5, 2, 6, 1, 7, 4, 8, 3] ; P = [6, 3, 5, 7, 1, 4, 2, 8] ; P = [6, 4, 7, 1, 3, 5, 2, 8] ; P = [3, 6, 2, 7, 5, 1, 8, 4] ; P = [6, 3, 1, 7, 5, 8, 2, 4] ; P = [6, 2, 7, 1, 3, 5, 8, 4] ; P = [6, 4, 7, 1, 8, 2, 5, 3] ; P = [3, 6, 2, 7, 1, 4, 8, 5] ; P = [6, 3, 7, 2, 4, 8, 1, 5] ; … Yukarıdaki orneklerde gorulduğu uzere her kolon icin, o kolondaki kacıncı satıra vezir yerleştirilebileceği ve bu yerleştirme işlemine gore butun kuralları sağlayan bir dizilimin nasıl elde edileceği listelenmiştir. Problemin birden fazla cozumu olduğu icin her satır, cozumlerden birisini gostermektedir. Orneğin ilk cozum satırını ele alırsak, aşağıdaki gibi bir satranc tahtası elde ederiz. P = [5, 2, 6, 1, 7, 4, 8, 3] ; Kodda, kabaca butun ihtimalleri deneyen bir permutasyon algoritması geliştirilmiştir. Ardından koşulların sağlanıp sağlanmadığı kontrol edilmiş ve buna gore koşulları sağlayan ihtimaller sonuc olarak dondurulmuştur. Algoritma, bir arama algoritması (search algorithm) şeklinde probleme yaklaştığı icin, problemin cozumu sırasındaki butun ihtimaller sadece bir kere denenecek ve denenen bir ihtimal tekrar etmeyecektir. Bu deneme sırası, permutasyon fonksiyonu ile sağlanır.
__________________
Prolog nedir
Programlama0 Mesaj
●36 Görüntüleme
- ReadBull.net
- Programlama ve Yazılım
- Programlama
- Prolog nedir