<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bilgisayar Kavramları &#187; yapay zeka (artificial intelligence)</title>
	<atom:link href="http://www.bilgisayarkavramlari.com/category/yapay-zeka-artificial-intelligence/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bilgisayarkavramlari.com</link>
	<description>www.bilgisayarkavramlari.com</description>
	<lastBuildDate>Sun, 29 Jan 2012 21:38:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>İleri ve geri zincirleme (Forward and Backward Chaining)</title>
		<link>http://www.bilgisayarkavramlari.com/2012/01/16/ileri-ve-geri-zincirleme-forward-and-backward-chaining-2/</link>
		<comments>http://www.bilgisayarkavramlari.com/2012/01/16/ileri-ve-geri-zincirleme-forward-and-backward-chaining-2/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 23:11:36 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[Mantık Devreleri (Logic Circuits)]]></category>
		<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/?p=6128</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Bu yazının amacı, bilgisayar bilimlerinde, özellikle de mantıksal sistemlerin ispatında kullanılan ileri zincirleme ve geri zincirleme yöntemlerini açıklamaktır. Yöntemin çalışması oldukça basittir. Öncelikle problem, mantık düzleminde modellenir. Buradaki mantık sistemi sonlu ispatı olan herhangi bir system olabilir. Örneğin birinci dereceden mantık (first order logic) veya daha özel olarak boole cebiri [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan : Şadi Evren ŞEKER
</p>
<p>Bu yazının amacı, bilgisayar bilimlerinde, özellikle de mantıksal sistemlerin ispatında kullanılan ileri zincirleme ve geri zincirleme yöntemlerini açıklamaktır.
</p>
<p>Yöntemin çalışması oldukça basittir. Öncelikle problem, mantık düzleminde modellenir. Buradaki mantık sistemi sonlu ispatı olan herhangi bir system olabilir. Örneğin <a href="http://www.bilgisayarkavramlari.com/2010/03/24/birinci-derece-mantik-first-order-logic/">birinci dereceden mantık (first order logic) </a> veya daha özel olarak boole cebiri kullanılabilir.
</p>
<p>Modelleme aşamasının ardından problemin çözümüne geçilir. İşte tam bu noktada ileri zincirleme (forward chaining) veya geri zincirleme (backward chaining) yöntemlerinden birisi seçilebilir.
</p>
<p>Örneğin aşağıdaki mantıksal sistemi ve şekli ele alalım:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz1.png" alt=""/>
	</p>
<p>Sistemde görüldüğü üzere bazı mantıksal dizilimler verilmiş ve son iki satırda A ve B önermelerinin (kaziye) doğru olduğu belirtilmiştir.
</p>
<p>Buna göre sağdaki çizim, hangi durumlarda, hangi diğer durumların doğru olacağını bu mantıksal sistemden çıkarır. Örneğin p=&gt; q ifadesi, çizimin en tepesinde gösterilmiş ve p önermesinin (predicate, kaziyesinin) doğruluğu halinde q önermesinin de (kaziyesinin de) doğru olacağını ifade etmektedir.
</p>
<p>Benzer şekilde, L <a href="http://www.bilgisayarkavramlari.com/2009/05/07/haber-predicate/">önermesinin (kaziyesinin)</a> doğruluğu A ve B önermelerine bağlı olduğu gibi, A ve P önermelerinin doğruluğuna da bağlanmıştır. Bu iki sistemden birisinin doğru olması sonucun doğruluğunu sağlar.
</p>
<p>Şimdi şekilde gösterilen sistemi ileri zincirleme (forward chaining) yöntemi ile çözelim. Öncelikle sistemdeki bütün doğruluk şartlarını sayısal olarak ifade ediyoruz:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz2.png" alt=""/>
	</p>
<p>Şekilde görüldüğü üzere bütün doğruluk şartları birer sayı ile ifade edilmiştir. Söz gelimi, M önermesinin doğruluğu L ve B önermesi gibi 2 önermenin doğruluğunu gerektirir. Bu yüzden M birleşiminde 2 sayısı bulunur. Benzer şekilde Q önermesinde bulunan 1 sayısı, sadece P önermesinin doğruluğunun yeterli olduğunu ifade etmektedir.
</p>
<p>Şimdi ileri zincirleme yöntemini kullanarak sistemin doğru olduğu verilen A ve B önermelerinden itibaren çözümünü izleyelim.
</p>
<p>Öncelikle A ve B&#8217;ye komşu olan düğümlerdeki değerleri 1&#8242;er azaltıyoruz:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz3.png" alt=""/>
	</p>
<p>Yukarıdaki şekilde ileri zincirleme işlemi (forward chaingin) A önermesi için çalıştırılmış olup A&#8217;nın komşularını 1 azaltmıştır. Sırada B önermesi var ve onu da çalıştıralım:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz4.png" alt=""/>
	</p>
<p>Görüldüğü üzere B&#8217;nin komşuları da 1 azaldığında 0 değerine sahip bir düğüm elde ettik. Bu durumda L&#8217;nin doğru olduğunu söyleyebiliriz çünkü L&#8217;nin doğru olması için gereken 2 değer de sağlandı. Yani mantıksal sistemimizde bulunan
</p>
<p>A <span style="font-family:Symbol">Ù</span> B <span style="font-family:Symbol">Þ</span> L
</p>
<p>Satırını sağlamış olduk. Buradan doğruluğunu bulduğumuz L önermesinin komşularını 1 azaltıyoruz:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz5.png" alt=""/>
	</p>
<p>L&#8217;nin komşularının 1 azalması sonucunda M&#8217;nin değeri 0&#8242;a inmişi oluyor ve artık M için de doğru diyebiliyoruz. Şimdi M&#8217;nin komşularını 1 azaltalım:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz6.png" alt=""/>
	</p>
<p>Artık P için doğru sonucuna ulaştık ve P&#8217;nin iki komşusununda değerini 1 azaltarak sonucu buluyoruz:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz7.png" alt=""/>
	</p>
<p>Görüldüğü üzere zaten doğru olduğunu bildiğimiz L için tekrar doğru sonucunu bulduk ve ilave olarak Q için de doğru sonucunu bulduk.
</p>
<p>Demek ki ilk  sistem bize verildiğinde, Q&#8217;nun değeri sorulsaydı, doğru olduğunu söyleyebilirdik, ancak bunu bilgisayarın bulması için yukarıda adım adım anlatılan aşamaların tamamlanması gerekmektedir.
</p>
<p><strong>Geri Zincirleme (Backward Chaining)<br />
</strong></p>
<p>Gelelim aynı amaç için kullanılan, yani bir mantıksal sistemi çözmek için kullanılan geri zincirleme yöntemine. İleri zincirleme yöntemine çok benzer olarak yine bir mantıksal sistem, bir şekil üzerinde gösterilebilr:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz8.png" alt=""/>
	</p>
<p>Sistemde diyelim ki Q&#8217;nun değerini merak ediyor olalım. Bilgisayar algoritması, bu defa Q&#8217;nun değerinin doğruluğunun P&#8217;nin değerinin doğruluğuna bağlı olduğunu çözerek işe başlayacaktır. Aslında geri zincirlemede kullanılan yaklaşım, tam olarak ileri zincirlemenin tersidir. İleri zincirlemede, doğruluğunu bildiğimiz önermelerden başlanırken, geri zincirlemede, doğruluğunu aradığımız önermelerden başlıyoruz. Burada doğruluğunu aradığımız önerme Q olduğuna göre, Q&#8217;dan başlayarak sistemi dolaşacağız. İlk adımda Q&#8217;nun doğruluğu, P&#8217;nin doğruluğuna bağlıdır, o halde Q yerine P doğru mudur diye sistemi çözmeye çalışırız:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz9.png" alt=""/>
	</p>
<p>P&#8217;nin doğruluğu, şekilde de görüldüğü üzere, L ve M&#8217;ye bağlıdır ve artık L ve M doğru mudur diye sorarız. Bunlardan birisinin yanlış olması halinde sonuç yanlış veya ikisinin de doğru olması halinde sonuç doğru olacaktır. Burada sonuç ile kastedilen P ve dolayısıyla Q&#8217;dur. Dikkat edilirse artık L ve M&#8217;ye bakarak Q&#8217;nun değerini tahmin edebiliyoruz. Devam edelim:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz10.png" alt=""/>
	</p>
<p>L&#8217;nin doğruluğuna bakıldığında P ve A bulunmakta, aslında bu sorunun cevabını P&#8217;nin değerini bilmediğimiz için veremeyiz. Ancak burada bir tehlike bizi bekliyor, şayet doğruluğunu araştırmak için DFS (depth first search, derin öncelikli arama) benzeri bir algoritma ile ağacı (veya şekli (graph) ) dolaşıyorsak, bu durumda bir sonsuz döngüye (fasit daire) girme ihtimalimiz bulunuyor. Bunu engellemek için diyelim ki derinliği sabitledik ve L&#8217;nin doğruluğu için A ve B ikilisine bakmaya karar verdik:
</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/011512_2311_lerivegeriz11.png" alt=""/>
	</p>
<p>Sonuçta A ve B doğru ise L doğru demektir. O halde L doğru mu sorusunu sormayı bırakıyor ve M doğrumu A ve B doğru mu sorularını arayarak sistemi çözmeye devam ediyoruz. M&#8217;nin doğruluğu ise L ve B&#8217;ye dayanmakta, o halde bir kere daha L&#8217;nin doğruluğunu sorguluyor ve yukarıda anlatıldığı üzere bir kere daha A ve B&#8217;nin doğruluğunu sorguluyoruz. Neticede sorumuz basitçe A ve B doğru mudur şeklinde oluyor.
</p>
<p>Verilen mantıksal sistemden de bildiğimiz üzere A ve B doğrudur, o halde Q da doğrudur diyebiliriz, çünkü sistemi buraya kadar adım adım çözdük ve neticede Q&#8217;nun doğruluğunu sorgulamanın A ve B&#8217;nin doğruluğunu sorgulamak olduğunu gördük.
</p>
<p>Geri zincirleme (backward chaining) yaklaşımında istenirse buradan geriye dönülerek bütün sistemdeki önermelerin durumları doğru veya yanlış olarak işaretlenebilir. Ancak geri zincirleme algoritması, bu aşamada aranan Q önermesinin sonucunu bularak durabilir de. Bu iki yaklaşım arasındaki fark aslında CPS (call by passing style) ile birikimsel tarz (accumulation style) arasındaki fark gibidir.
</p>
<p>İki yöntemde de sonuç doğru bir şekilde bulunur. Belki ufak bir fark olarak dikkat edilmesi gereken, geri zincirlemede, özel olarak aranan bir önermenin sonucuna konsantre olmamız, buna bağlı olarak da bazı büyük sistemlerde, sistemin sadece belirli bir kısmını çözüyor olmamız görülebilir. Buna mukabil, ileri zincirleme yaklaşımında, sistemin tamamı çözülmektedir.</p>

<p class="sayac_bilgi">40 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2012/01/16/ileri-ve-geri-zincirleme-forward-and-backward-chaining-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PROLOG</title>
		<link>http://www.bilgisayarkavramlari.com/2012/01/15/prolog/</link>
		<comments>http://www.bilgisayarkavramlari.com/2012/01/15/prolog/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 00:40:27 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[Programlama Dilleri]]></category>
		<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/?p=6091</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Bu yazının amacı, PROLOG diline giriş yapmak ve basit bazı yapay zeka problemlerinin PROLOG dilinde nasıl kodlanarak çözüldüğünü göstermektir. Kurulum ve çalıştırma: Bu yazı kapsamında SWI-PROLOG programı kullanılacaktır. Programı, www.swi-prolog.com adresinden temin etmek mümkündür. Yazı kapsamında MAC OSX üzerinde örnekler çalıştırılarak gösterilecektir ancak kurulum ve sonrasında başarılı bir çalıştırma yapılabiliyorsa [...]]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal">Yazan : Şadi Evren ŞEKER</p>
<p class="MsoNormal"><span lang="TR">Bu yazının amacı, PROLOG diline giriş yapmak ve basit bazı yapay zeka problemlerinin PROLOG dilinde nasıl kodlanarak çözüldüğünü göstermektir. </span></p>
<p class="MsoNormal"><strong><span lang="TR">Kurulum ve çalıştırma:</span></strong></p>
<p class="MsoNormal"><span lang="TR">Bu yazı kapsamında SWI-PROLOG programı kullanılacaktır. Programı, </span><a href="http://www.swi-prolog.com/"><span lang="TR">www.swi-prolog.com</span></a><span lang="TR"> adresinden temin etmek mümkündür. </span></p>
<p class="MsoNormal"><span lang="TR">Yazı kapsamında MAC OSX üzerinde örnekler çalıştırılarak gösterilecektir ancak kurulum ve sonrasında başarılı bir çalıştırma yapılabiliyorsa hangi işletim sisteminde olduğunuzun bir önemi yoktur, bütün sistemlerde aynı PROLOG komutları çalışır. </span></p>
<p class="MsoNormal"><span lang="TR">Siteden indirilip kurulum yapıldıktan sonra, </span></p>
<p class="MsoNormal"><tt><span style="font-size: 10pt;" lang="TR">$ /opt/local/bin/swipl</span></tt><span lang="TR"> </span></p>
<p class="MsoNormal"><span lang="TR">Dizini altında bulunan swipl komutu çalıştırılarak, PROLOG komut satırı açılabilir. </span></p>
<p class="MsoNormal"><span lang="TR">Program çalıştırıldığında, aşağıdakine benzer bir komut satırı ile komut girilmesini bekleyecektir:</span></p>
<p class="MsoNormal"><tt><span style="font-size: 10pt;" lang="TR">?- _</span></tt></p>
<p class="MsoNormal"><strong><span lang="TR">Yardım</span></strong></p>
<p class="MsoNormal"><span lang="TR">İlk ve en önemli komutumuz olan yardım komutu ile başlayabiliriz. </span></p>
<p class="MsoNormal"><tt><span style="font-size: 10pt;" lang="TR">?- help(help).</span></tt></p>
<p class="MsoNormal"><span lang="TR">Bu komut, X11 ekranında, yardım dokümanını görüntüleyecektir. Basitçe 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 için yardım alınmıştır. </span></p>
<p class="MsoNormal"><strong><span lang="TR">Çıkış</span></strong></p>
<p class="MsoNormal"><span lang="TR">Prolog komut satırından çıkmak için </span></p>
<p class="MsoNormal"><tt><span style="font-size: 10pt;" lang="TR">?- halt.</span></tt></p>
<p class="MsoNormal"><span lang="TR">Yazılması yeterlidir. Bu komut programı sonlandıracaktır. </span></p>
<p class="MsoNormal"><strong><span lang="TR">Basit Kaziyeler</span></strong></p>
<p class="MsoNormal"><span lang="TR">Aşağıdaki komutları PROLOG üzerinde çalıştıralım ve ardından burada yapılan işlemleri yorumlayalım.</span></p>
<p class="MsoNormal"><span lang="TR">Sistemimizde kayıtlı olan bir dosyayı program tarafından açıp çalıştırılır bir şekilde yüklemek için dosya ismi köşeli parantezler içerisinde verilmelidir:</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: Courier;" lang="TR">?- [‘ilkdosya.pl'].</span></p>
<p class="MsoNormal"><span lang="TR">Yukarıda, bilgisayarımızda bulunan “ilkdosya.pl” isimli dosyayı sisteme tanıtarak yükledik. Bu dosyada bulunan tanımlar da otomatik olarak yüklenmiş ve sorgulanmaya / çalışmaya hazır hale getirilmiş olacaktır. Ayrıca bu dosyada bulunan genel hatalar, yükleme sırasında ekrana basılır.<br />
</span></p>
<p class="MsoNormal"><strong><span lang="TR">PROLOG ile Faktöriyel Kodu</span></strong></p>
<p class="MsoNormal"><span lang="TR">PROLOG dili, yapısal olarak özyineli (recursive) bir yapıdadır ve döngülerin yerine özyineli fonksiyon (recursive function) kullanılması gerekir. Bu kullanımı göreceğimiz en basit uygulamalardan birisi olan faktöriyel kodunu yazıp kodlamaya çalışalım.</span></p>
<p class="MsoNormal"><span lang="TR">Herhangi bir editör açılarak (ben tercihen vi kullanıyorum, siz de istediğiniz bir editör ile dosyayı açıp içeriğini ) aşağıdaki şekilde yazabilirsiniz:</span></p>
<pre><span lang="TR">factorial(0,1).      </span></pre>
<pre><span lang="TR">factorial(A,B) :- </span></pre>
<pre><span lang="TR">             A &gt; 0,</span></pre>
<pre><span lang="TR">             C is A-1,</span></pre>
<pre><span lang="TR">            factorial(C,D),</span></pre>
<pre><span lang="TR">            B is A*D. </span></pre>
<p class="MsoNormal"><span lang="TR">Ardından aşağıdaki şekilde dosyamızı sisteme yükleyelim:</span></p>
<p class="MsoNormal"><span lang="TR">?- ['ilkdosya.pl'].</span></p>
<p class="MsoNormal"><span lang="TR">% ilkdosya.pl compiled 0.00 sec, 732 bytes</span></p>
<p class="MsoNormal"><span lang="TR">true.</span></p>
<p class="MsoNormal"><span lang="TR"> </span></p>
<p class="MsoNormal"><span lang="TR">Komut satırında dosyamızın yüklendiği ve yükleme süresi ve dosya boyutu gösterilmektedir. Son satırda yer alan true bilgisine kadar bir hata bulunmamış olması, dosyamızda bir hata olmadığını gösterir. Şimdi artık ilk fonksiyonumuzu kullanmaya başlayabiliriz. </span></p>
<p class="MsoNormal"><span lang="TR">?- factorial(5,X).</span></p>
<p class="MsoNormal"><span lang="TR">X = 120 ;</span></p>
<p class="MsoNormal"><span lang="TR">false.</span></p>
<p class="MsoNormal"><span lang="TR"> </span></p>
<p class="MsoNormal"><span lang="TR">Komut satırında, factorial(5,X) komutu verilerek, 5! Değerinin X değişkenine döndürülmesi istenmiştir. Burada öğrenilen birkaç önemli noktayı belirtelim. Birincisi X ile gösterilen değer bir değişkendir ve PROLOG dünyasında buna unbounded variable (bağlanmamış değişken) ismi verilir. Basitçe Prolog kodlarındaki bütün büyük 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 göre yüklü olan dosyada bulunan komutlar yukarıdan aşağıya doğru çalıştırılırken üstte bulunan satır, alttakine gore öncelikli olur ve aynı zamanda birden fazla satırda emirin tanımlanması durumunda, sırasıyla bu emirler işlenir. </span></p>
<p class="MsoNormal"><span lang="TR">Örneğ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 faktöriyeli sorarsa, ikinci değer olarak 1 sonucunu döndürmeyi gerektirir. </span></p>
<p class="MsoNormal"><span lang="TR">İkinci satırdan sonra başlayan tanımda ise, sırasıyla A&gt;0 kontrolü yapılmış, ardından C değişkenine değer olarak A-1 değeri konmuş ve yeni bulunan C değerinin faktöriyeli hesaplanarak, B sonucuna hesaplanan bu C faktöriyel değeri ile A’nın çarpımı eklenmiştir. </span></p>
<p class="MsoNormal"><span lang="TR">Yukarıdaki şekilde kodumuzu ilkdosya.pl<span>  </span>dosyasına yazıp kaydettikten sonra prolog komut satırında dosyamızı yükleyip çalıştırabiliriz:</span></p>
<p class="MsoNormal"><span lang="TR"> <a href="http://www.bilgisayarkavramlari.com/wp-content/uploads/Untitled2.png"><img class="alignnone  wp-image-6106" title="Untitled2" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/Untitled2.png" alt="" width="510" height="235" /></a></span></p>
<p class="MsoNormal"><span lang="TR">Yukarıda görüldüğü üzere faktöriyel kodumuz çalışmış ve sonucu doğru şekilde bulmuştur. </span></p>
<p class="MsoNormal"><span lang="TR">Kodun çalışmasını takip etmek için trace komutu kullanılabilir. Basitçe komut satırında:</span></p>
<p class="MsoNormal"><span lang="TR">trace.</span></p>
<p class="MsoNormal"><span lang="TR">Yazıldıktan sonra çalışmaya başlar ve bu çalışmadan sonra çağrılan fonksiyonların detayları ekrana basılır:</span></p>
<p class="MsoNormal"><span><a href="http://www.bilgisayarkavramlari.com/wp-content/uploads/Untitled1.png"><img class="alignnone  wp-image-6107" title="Untitled" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/Untitled1.png" alt="" width="311" height="708" /></a></span></p>
<p class="MsoNormal"><span lang="TR">Görüldüğü üzere factorial fonksiyonumuzun her adımı ekrana basılmıştır.</span></p>
<p class="MsoNormal"><strong><span lang="TR">Hanoi Kuleleri (Towers of Hanoi)</span></strong></p>
<p class="MsoNormal"><span lang="TR">İkinci bir uygulama olarak çok klasik bilgisayar bilimleri problemlerinden olan Hanoi Kulelerini ( tower of hanoi ) kodlamaya çalışalım.</span></p>
<p class="MsoNormal"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeEAAADICAYAAADfnllEAAADHmlDQ1BJQ0MgUHJvZmlsZQAAeAGFVN9r01AU/tplnbDhizpnEQk+aJFuZFN0Q5y2a1e6zVrqNrchSJumbVyaxiTtfrAH2YtvOsV38Qc++QcM2YNve5INxhRh+KyIIkz2IrOemzRNJ1MDufe73/nuOSfn5F6g+XFa0xQvDxRVU0/FwvzE5BTf8gFeHEMr/GhNi4YWSiZHQA/Tsnnvs/MOHsZsdO5v36v+Y9WalQwR8BwgvpQ1xCLhWaBpXNR0E+DWie+dMTXCzUxzWKcECR9nOG9jgeGMjSOWZjQ1QJoJwgfFQjpLuEA4mGng8w3YzoEU5CcmqZIuizyrRVIv5WRFsgz28B9zg/JfsKiU6Zut5xCNbZoZTtF8it4fOX1wjOYA1cE/Xxi9QbidcFg246M1fkLNJK4RJr3n7nRpmO1lmpdZKRIlHCS8YlSuM2xp5gsDiZrm0+30UJKwnzS/NDNZ8+PtUJUE6zHF9fZLRvS6vdfbkZMH4zU+pynWf0D+vff1corleZLw67QejdX0W5I6Vtvb5M2mI8PEd1E/A0hCgo4cZCjgkUIMYZpjxKr4TBYZIkqk0ml0VHmyONY7KJOW7RxHeMlfDrheFvVbsrj24Pue3SXXjrwVhcW3o9hR7bWB6bqyE5obf3VhpaNu4Te55ZsbbasLCFH+iuWxSF5lyk+CUdd1NuaQU5f8dQvPMpTuJXYSWAy6rPBe+CpsCk+FF8KXv9TIzt6tEcuAcSw+q55TzcbsJdJM0utkuL+K9ULGGPmQMUNanb4kTZyKOfLaUAsnBneC6+biXC/XB567zF3h+rkIrS5yI47CF/VFfCHwvjO+Pl+3b4hhp9u+02TrozFa67vTkbqisXqUj9sn9j2OqhMZsrG+sX5WCCu0omNqSrN0TwADJW1Ol/MFk+8RhAt8iK4tiY+rYleQTysKb5kMXpcMSa9I2S6wO4/tA7ZT1l3maV9zOfMqcOkb/cPrLjdVBl4ZwNFzLhegM3XkCbB8XizrFdsfPJ63gJE722OtPW1huos+VqvbdC5bHgG7D6vVn8+q1d3n5H8LeKP8BqkjCtbCoV8yAAAL9UlEQVR4Ae3dAXLiRhAFUJPa+1+ZmGSNBQJbiJFm+uttVSpYBk3367F/pFDL6fz558MfAgQIECBAYHeBf3Zf0YIECBAgQIDAfwJC2EYgQIAAAQKdBIRwJ3jLEiBAgAABIWwPECBAgACBTgJCuBO8ZQkQIECAgBC2BwgQIECAQCcBIdwJ3rIECBAgQEAI2wMECBAgQKCTgBDuBG9ZAgQIECAghO0BAgQIECDQSUAId4K3LAECBAgQEML2AAECBAgQ6CQghDvBW5YAAQIECAhhe4AAAQIECHQSEMKd4C1LgAABAgSEsD1AgAABAgQ6CQjhTvCWJUCAAAECQtgeIECAAAECnQSEcCd4yxIgQIAAASFsDxAgQIAAgU4Cfzqte4hlT6fTrM/z+Tw75gABe8UeuAjYB8fbB66EN5r5ox+mZz9kG5XgtEUE7JUig9q4TPtgY+BBTy+ENxjMsx+mr6V++/7X8/w7X+C3vfDb9/OFjtHhb3P+7fvHUMrsUgg3nuv8h+Vy+/nrn+/F5s/7/p5HxxCY74GvfXL7vyzmzzuGz1G6nM/XPjjK7C99CuFNp337y/T/MN50QScvK2CvlB1d08Ltg6acBU4mhAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCkghDPnqisCBAgQKCAghAsMSYkECBAgkCnwJ7Ot97s6nU7vn+Tj53O8s8b5fG5Qn1MQIECAQE8BV8IP9N8Jxwen2+RQhRo3adxJCRAgECQghO+GWSncKtV6x+xLAgQIEPgUcDt6sg1moTbqLd/JrfJLzW5NT4boIQECBAoJuBJ+NqxRA/hS78i1PfN0nAABAgRmAkJ4RuIAAQIECBDYR0AI7+NsFQIECBAgMBMQwjMSBwgQIECAwD4CQngfZ6sQIECAAIGZgBCekThAgAABAgT2ERDC+zhbhQABAgQIzASE8IzEAQIECBAgsI+AEN7H2SoECBAgQGAmIIRnJA4QIECAAIF9BITwPs5WIUCAAAECMwEhPCNxgAABAgQI7CMghPdxtgoBAgQIEJgJCOEZiQMECBAgQGAfASH8zHnycYHPntLt+Mi1dUOxMAECBOoJ+Dzhycwun8t785nCBcLOZwlPBughAQIEigm4Er4bWKVQq1TrHbMvCRAgQOBTQAg/2AYVwq1CjQ9oHSJAgACBiYDb0ROM6cO1IXdzO/vjPD3l38en67G1a1xP4AEBAgQIlBZwJVx6fIonQIAAgcoCQrjy9NROgAABAqUFhHDp8SmeAAECBCoLCOHK01M7AQIECJQWEMKlx6d4AgQIEKgsEPfu6Nt3J/cezfc7oR9V0rtW785+NBXHCBAgsJ9A1JVw71Dbb2xtVuLVxtFZCBAgsFYgJoQFyrotwG2dm1cRIECghUDE7ehZkHz+HdD+/CIw+XuxL35uTf/i5dsECBDYQCDmSvhqI4CvFD8+4PQjj28SIEBgD4G8EN5DzRoECBAgQKCBgBBugOgUBAgQIEBgjYAQXqPmNQQIECBAoIGAEG6A6BQECBAgQGCNgBBeo+Y1BAgQIECggYAQboDoFAQIECBAYI2AEF6j5jUECBAgQKCBgBBugOgUBAgQIEBgjYAQXqPmNQQIECBAoIGAEG6A6BQECBAgQGCNgBBeo+Y1BAgQIECggYAQboDoFAQIECBAYI2AEF6j5jUECBAgQKCBQF4ITz6ir4FP7ik45c5WZwQIlBGI+Dzhy2fh3nymsIB5aQP6LOGXuDyZAAECzQRiroQFybo9wW2dm1cRIECghUBMCF8wBMprW4LXa16eTYAAgdYCEbejpyi9g+XmtvjHeVra38en67HetV4L8YAAAQIEughEXQl3EbQoAQIECBBYKSCEV8J5GQECBAgQeFdACL8r6PUECBAgQGClgBBeCedlBAgQIEDgXQEh/K6g1xMgQIAAgZUCQ707+vadxSs7Gupl3++EflRWQr/e4f1oso4RIEBgmcAwV8IJgbSMPOtZ5pY1T90QILCvwBAh7Bf5vkNvvZr5tRZ1PgIEjiLQ/Xb07Bf4598D7U8Rgcnf0X2Zo1vTReamTAIEhhEY4kr4qiGArxQlHphXiTEpkgCBcQXGCuFxnVRGgAABAgSaCwjh5qROSIAAAQIElgkI4WVOnkWAAAECBJoLCOHmpE5IgAABAgSWCQjhZU6eRYAAAQIEmgsI4eakTkiAAAECBJYJCOFlTp5FgAABAgSaCwjh5qROSIAAAQIElgkI4WVOnkWAAAECBJoLCOHmpE5IgAABAgSWCQjhZU6eRYAAAQIEmgsI4eakTkiAAAECBJYJCOFlTp5FgAABAgSaC4wVwpOPxmveqRO2FzCv9qbOSIDAoQS6f57w5TNobz5T2C/2khvQZwmXHJuiCRDoLDDElbBf4J13wZvLm9+bgF5OgMBhBYYI4Yu+X+Q196C51ZybqgkQGEOg++3oKUPCL/SbW+sf52l7fx+frscS+r024wEBAgQIvCwwzJXwy5V7AQECBAgQKC4ghIsPUPkECBAgUFdg89vRt7dn60JtUTmbLVQzz2mvZM711a7sg1fFlj2/5/8a3CyEbZZlw/csAgQIEOgr8JVXPcJ4k9vRXw31ZR1h9e83Yf1fzf3XI9SohjEE7vfG/ddjVKmKrQXu537/9dbrH/v8PbJrsyvhY49y2r0foqmGxz8J2Cs/6Rzne/bBcWb98dH8SrjHf0kcaWB6JUCAAIEcgeYhnEOjEwIECBAgsK2AEN7W19kJECBAgMBTgeYh3OPdZU+78w0CBAgQIDCwQPMQHrhXpREgQIAAgaEENnl3tKvhoWasGAIECBAYVMCV8KCDURYBAgQI5AsI4fwZ65AAAQIEBhUQwoMORlkECBAgkC8ghPNnrEMCBAgQGFRACA86GGURIECAQL6AEM6fsQ4JECBAYFABITzoYJRFgAABAvkCQjh/xjokQIAAgUEFhPCgg1EWAQIECOQLCOH8GeuQAAECBAYVEMKDDkZZBAgQIJAvIITzZ6xDAgQIEBhUQAgPOhhlESBAgEC+gBDOn7EOCRAgQGBQASE86GCURYAAAQL5AkI4f8Y6JECAAIFBBYTwoINRFgECBAjkCwjh/BnrkAABAgQGFRDCgw5GWQQIECCQLyCE82esQwIECBAYVEAIDzoYZREgQIBAvoAQzp+xDgkQIEBgUAEhPOhglEWAAAEC+QJCOH/GOiRAgACBQQWE8KCDURYBAgQI5AsI4fwZ65AAAQIEBhUQwoMORlkECBAgkC8ghPNnrEMCBAgQGFRACA86GGURIECAQL6AEM6fsQ4JECBAYFABITzoYJRFgAABAvkCQjh/xjokQIAAgUEF/gWdCJj2GkovIAAAAABJRU5ErkJggg==" alt="" /></p>
<p class="MsoNormal"><span lang="TR">Oyunun kuralı gayet basit. Başlangıçta bir çubukta dizili olan bütün diskler her adımda tek bir disk hareket ettirerek diğer iki çubuktan birisine taşınacaktır. Bu taşıma işlemleri sırasında büyük bir disk, küçük olan bir diskin üzerine gelmeyecektir. </span></p>
<p class="MsoNormal"><span lang="TR">Ayrıca oyunun internetten oynan bir denemesi için daha önce hazırladığım aşağıdaki ödev sayfasına bakabilirsiniz:</span></p>
<p class="MsoNormal"><a href="http://www.sadievrenseker.com/c/odev5.html"><span lang="TR">http://www.sadievrenseker.com/c/odev5.html</span></a></p>
<p>Problemin çözümünde kullanacağımız kod aşağıdaki şekildedir:</p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">SADIs-MacBook-Air:prolog sadievrenseker$ vi hanoi.pl </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">oyna(1,X,Y,_) :-</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    write(X),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    write(&#8216; en üstteki diskini &#8216;),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    write(Y),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    write(&#8216; oynat &#8216;),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    nl.</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">oyna(N,X,Y,Z) :-</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    N&gt;1,</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    M is N-1,</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    oyna(M,X,Z,Y),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    oyna(1,X,Y,_),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">    oyna(M,Z,Y,X).</span></p>
<p class="MsoNormal"><span lang="TR">Kod örneği yukarıda verilmiştir. Kodumuzun çalışmasını görüp ardından nasıl çalıştığını açıklamaya geçebiliriz. </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR"> </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">?- oyna(4,a,b,c).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini c oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">c en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini c oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">b en üstteki diskini a oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">b en üstteki diskini c oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini c oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">c en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">c en üstteki diskini a oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">b en üstteki diskini a oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">c en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini c oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">c en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">true .</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">?-</span></p>
<p class="MsoNormal"><span lang="TR">Yukarıdaki çalışmadan da görüldüğü üzere ilk baştaki 4 diskin dizili olduğu a çubuğundan bütün diskler sırasıyla b çubuğuna taşınmıştır.<br />
</span></p>
<p class="MsoNormal"><span lang="TR">Kodumuz, doğru sıra ile oynama yaklaşımı ile kodlanmıştır. Hanoi kulelerinin farklı çözümleri bulunur. Örneğin geri izleme algoritması (backtracking) kullanarak kaba kuvvetle (brute force) bütün ihtimallerin denendiği ve başarısızlık olması halinde en son iyi duruma geri dönen yaklaşımları kodlamak da mümkündür. </span></p>
<p class="MsoNormal"><span lang="TR">Bizim kodlamamızda ise her seferinde doğru çubuktan doğru diskin oynatılması esası kullanılmıştı. Bu yüzden hiç geri oynama veya yapılan hamleden vaz geçme olmamıştır. </span></p>
<p class="MsoNormal"><span lang="TR">Bu oynama esasını daha iyi anlatabilmek için daha ufak bir örnek üzerinden çalışmayı gösterelim :</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">?- oyna(2,a,b,c).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini c oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">a en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">c en üstteki diskini b oynat </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">true </span></p>
<p class="MsoNormal"><span lang="TR"> </span></p>
<p class="MsoNormal"><span lang="TR">Görüldüğü üzere iki disklik bir dizilimde, c çubuğu geçici olarak kullanılmakta, esas büyük diskin b çubuğuna oynanması sırasında, küçük diskleri depolamak için kullanılmaktadır. </span></p>
<p class="MsoNormal"><span lang="TR">Bu durum disk sayısı artsa da değişmez. En büyük diskin a çubuğundan b çubuğuna oynanması sırasında,<span>  </span>diğer bütün küçük diskleri depolamak için c çubuğunu kullanırız. Buradan anlaşılacağı üzere ikinci büyük diskin c çubuğuna oynaması gerekir. Bunun için de b çubuğunu geçici depolama için kullanırız. Bu yaklaşım en büyük diskten en küçüğüne kadar aynı mantıkla işleyerek devam eder.<br />
</span></p>
<p class="MsoNormal"><strong><span lang="TR">8 Vezir Problemi (8 Queens Problem)</span></strong></p>
<p class="MsoNormal"><span lang="TR">Yeni bir problem olarak klasik sorulardan birisi olan 8 vezir problemini ( eight queens problem) ele alalım. Problem basitçe bir satranç tahtasına 8 veziri, birbirini yemeden nasıl yerleştireceğimizdir. </span></p>
<p class="MsoNormal"><span lang="TR"> </span><img src="data:image/png;base64,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" alt="" /></p>
<p class="MsoNormal"><span lang="TR">Problemin çözümü olan PROLOG kodu aşağıda verilmiştir.</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">perm([X|Y],Z) :- perm(Y,W), birinial(X,Z,W).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">perm([],[]).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR"> </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">birinial(X,[X|R],R).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">birinial(X,[F|R],[F|S]) :- birinial(X,R,S).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR"> </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">cozum(P) :-</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">     perm([1,2,3,4,5,6,7,8],P),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">     birlestir([1,2,3,4,5,6,7,8],P,S,D),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">     hepsifarkli(S),</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">     hepsifarkli(D).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR"> </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">birlestir([X1|X],[Y1|Y],[S1|S],[D1|D]) :-</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">     S1 is X1 +Y1,</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">     D1 is X1 &#8211; Y1,</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">     birlestir(X,Y,S,D).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">birlestir([],[],[],[]).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR"> </span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">hepsifarkli([X|Y]) :-  \+member(X,Y), hepsifarkli(Y).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">hepsifarkli([X]).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR"> </span></p>
<p class="MsoNormal"><span lang="TR">Kodun çalışan örneği aşağıdaki şekildedir:</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">?- cozum(P).</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [5, 2, 6, 1, 7, 4, 8, 3] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [6, 3, 5, 7, 1, 4, 2, 8] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [6, 4, 7, 1, 3, 5, 2, 8] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [3, 6, 2, 7, 5, 1, 8, 4] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [6, 3, 1, 7, 5, 8, 2, 4] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [6, 2, 7, 1, 3, 5, 8, 4] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [6, 4, 7, 1, 8, 2, 5, 3] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [3, 6, 2, 7, 1, 4, 8, 5] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [6, 3, 7, 2, 4, 8, 1, 5] ;</span></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">&#8230;</span></p>
<p class="MsoNormal"><span lang="TR"> </span></p>
<p class="MsoNormal"><span lang="TR">Yukarıdaki örneklerde görüldüğü üzere her kolon için, o kolondaki kaçıncı satıra vezir yerleştirilebileceği ve bu yerleştirme işlemine göre bütün kuralları sağlayan bir dizilimin nasıl elde edileceği listelenmiştir. Problemin birden fazla çözümü olduğu için her satır, çözümlerden birisini göstermektedir. Örneğin ilk çözüm satırını ele alırsak, aşağıdaki gibi bir satranç tahtası elde ederiz. </span></p>
<p class="MsoNormal"><span lang="TR"> </span><img src="data:image/png;base64,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" alt="" /></p>
<p class="MsoNormal"><span style="font-family: courier new,courier;" lang="TR">P = [5, 2, 6, 1, 7, 4, 8, 3] ;</span></p>
<p class="MsoNormal"><span lang="TR">Kodda, kabaca bütün ihtimalleri deneyen bir permütasyon algoritması geliştirilmiştir. Ardından koşulların sağlanıp sağlanmadığı kontrol edilmiş ve buna göre koşulları sağlayan ihtimaller sonuç olarak döndürülmüştür. </span></p>
<p class="MsoNormal"><span lang="TR">Algoritma, bir arama algoritması (search algorithm) şeklinde probleme yaklaştığı için, problemin çözümü sırasındaki bütün ihtimaller sadece bir kere denenecek ve denenen bir ihtimal tekrar etmeyecektir. Bu deneme sırası, permütasyon fonksiyonu ile sağlanır.<br />
</span></p>

<p class="sayac_bilgi">113 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2012/01/15/prolog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SimHash (Benzerlik Özeti)</title>
		<link>http://www.bilgisayarkavramlari.com/2011/11/19/simhash-benzerlik-ozeti/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/11/19/simhash-benzerlik-ozeti/#comments</comments>
		<pubDate>Sat, 19 Nov 2011 10:35:03 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[Doğal Dil İşleme (NLP)]]></category>
		<category><![CDATA[Dosya Organizasyonu (File Organisation)]]></category>
		<category><![CDATA[Veri Sıkıştırma (Data Compression)]]></category>
		<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/?p=6062</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Bilgisayar bilimlerinde, özellikle metin işlemenin yoğun olduğu, arama motoru gibi uygulamalarda dosyaların veya web sitelerinin birbirine olan benzerliğini bulmak için kullanılan bir algoritmadır. Algoritmaya alternatif olarak klasik hash fonksiyonları kullanılabilir. Yani, örneğin iki sayfasnın ayrı ayrı hash değerleri alınıp bu değerleri karşılaştırmak mümkündür. Ancak simhash algoritması, bu yönteme göre daha [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan : Şadi Evren ŞEKER</p>
<p>Bilgisayar bilimlerinde, özellikle metin işlemenin yoğun olduğu, arama motoru gibi uygulamalarda dosyaların veya web sitelerinin birbirine olan benzerliğini bulmak için kullanılan bir algoritmadır. </p>
<p>Algoritmaya alternatif olarak klasik <a href="http://www.bilgisayarkavramlari.com/2008/05/26/ozetleme-fonksiyonlari-hash-function/">hash fonksiyonları</a> kullanılabilir. Yani, örneğin iki sayfasnın ayrı ayrı hash değerleri alınıp bu değerleri karşılaştırmak mümkündür. Ancak simhash algoritması, bu yönteme göre daha fazla hız ve performans sunar. </p>
<p>Sim hash algoritması, iki dosyayı birer vektör olarak görür ve bu <a href="http://www.bilgisayarkavramlari.com/2008/01/12/mesafe-vektoru-distance-vector/">vektorler (yöney, vector)</a> arasındaki cosinüs (cosine) bağlantısını bulmaya çalışır. </p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/yoneykosinus.png" alt="Yoneykosinus" title="yoneykosinus.png" border="0" width="265" height="141" /></p>
<p>Yukarıdaki şekilde temsil edildiği üzere iki dokümanın ayrı ayrı birere vektör olması durumunda, aralarında cos (x) olarak gösterilen bir açı ile bağlantı bulunması mümkündür.</p>
<p>Algoritma, öncelikle işlediği metindeki kelimelerin ağırlıklarını (weight) çıkarmakta ve buna göre kelimeleri sıralamaktadır. </p>
<p>Sıralanan her kelimeye, b uzunluğunda, yegane (unique) değer döndüren bir fonksiyon kullanılır. Örneğin her kelime için farklı bir hash  sonucu döndüren fonksiyon kullanılır. </p>
<p>b boyutundaki bir vektörün ağırlık değeri hesaplanırken, her kelimedeki 1 değeri için +1 ve 0 değeri için -1 değeri ağırlığa eklenir.</p>
<p>Son olarak üretilen ağırlık vektöründeki + değerler 1, 0 ve &#8211; değerler ise 0 olarak çevirilir.</p>
<p><b>Örnek</b></p>
<p>Yukarıdaki algoritmanın çalışmasını bir örnek üzerinden anlatalım. Algoritmanın üzerinde çalışacağı metin aşağıdaki şekilde verilmiş olsun:</p>
<p>www bilgisayar kavramları com bilgisayar kavramlarının anlatıldığı bir bilgisayar sitesidir ve com uzantılıdır</p>
<p>Yukarıdaki bu metni, algoritmanın anlatılan adımlarına göre işleyelim:</p>
<p>İlk adımımız, algoritmadaki kelimelerini ağırlıklarının çıkarılmasıdır. Bu adımı çeşitli şekillerde yapmak mümkündür ancak biz örneğimizde kolay olması açısından kelime <a href="http://www.bilgisayarkavramlari.com/2008/02/21/veri-guvenliginde-frekans-analizi-cryptoanalysis/">frekanslarını (tekrar sayısı, frequency)</a> kullanacağız. Buna göre metindeki kelimelerin tekrar sayılarına göre sıralanmış hali aşağıda verilmiştir:</p>
<p>bilgisayar 3 com 2 kavramları 1 kavramlarının 1 anlatıldığı 1 bir 1 www 1 sitesidir 1 ve 1 uzantılıdır 1</p>
<p>Yukarıda geçen her kelime için bir parmak izi (fingerprint) değeri üretiyoruz. Bu değerin özelliği, kelimeler arasında yegane (unique) bir değer bulmaktır. Bu değer, herhangi bir hash fonksiyonu üzerinden de üretilebilir. Biz örneğimizde kolalık olması açısından her kelime için rast gele bir değer kendimiz atayacağız. Ancak gerçek bir uygulamada rast gele değerlerin kullanılması mümkün değildir. Bunun sebebi, aynı kelimenin tekrar gelmesi halinde yine aynı değerin üretilmesi zorunluluğudur. Bu yazıdaki amaç algoritmayı anlatmak olduğu için birer hash sonucu olarak rast gele değerler kullanılacaktır. </p>
<p>bilgisayar 10101010  com 11000000 kavramları 01010101 kavramlarının 10100101 anlatıldığı 11101110 bir 01011111 www 11110001 sitesidir 10101110 ve 00001111 uzantılıdır 00100010</p>
<p></p>
<p>3. adımda, yukarıdaki değerleri topluyoruz. Toplama işlemi sırasında 1 değerleri için +1 ve 0 değerleri için -1 alıyoruz.</p>
<p>
10101010<br />
11000000<br />
01010101<br />
10100101<br />
11101110<br />
01011111<br />
11110001<br />
10101110<br />
00001111<br />
00100010<br />
&#8212;&#8212;&#8211;<br />
2 0 2 -4 0 2 2 0
</p>
<p>Son olarak, yukarıdaki değerleri ikilik tabana çeviriyoruz: 10100110 bu değer bizi simhash sonucumuz olarak bulunuyor.</p>
<p>Örneğin yeni bir dosyayı daha işlemek istediğimizde, bu dosyadaki kelime yoğunluğuna göre yukarıda bulduğumuz simhash değerine yakın bir değer çıkmasını bekleriz. </p>
<p>Diyelim ki yeni bir dosyada da sadece &#8220;bilgisayar kavramları com&#8221; yazıyor olsun. Bu yazının sim hash değerini bularak karşılaştırmaya çalışalım:</p>
<p>bilgisayar 10101010  com 11000000 kavramları 01010101</p>
<p>
10101010<br />
11000000<br />
01010101<br />
&#8212;&#8212;&#8212;<br />
1 1 -1 -1 -1 1 1 1
</p>
<p>Değerin ikilik tabana çevrilmiş hali : 11000111</p>
<p>Orjinal dokümandan çıkardığımız simhash değeri ile farklı olan bit sayısı 3&#8242;tür. Bunun anlamı yukarıdaki bilgisayar kavramları com yazısının orjinal yazıya 3 mesafesinde yakın olduğudur. </p>

<p class="sayac_bilgi">136 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/11/19/simhash-benzerlik-ozeti/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sezgisel Fonksiyonlar (Heuristic Functions)</title>
		<link>http://www.bilgisayarkavramlari.com/2011/11/13/sezgisel-fonksiyonlar-heuristic-functions/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/11/13/sezgisel-fonksiyonlar-heuristic-functions/#comments</comments>
		<pubDate>Sun, 13 Nov 2011 18:58:16 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/?p=6051</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Bu yazının amacı, sezgisel algoritmalar (heuristic algorithms) tarafından kullanılan sezgisel fonksiyon (heuristic function) kavramını açıklamak ve bazı zaviyelerden tasnif etmektir. 1. Baskınlık Özelliği (Dominance) 2. Tutarlılık Özelliği (Consistent, Monotone) 3. Makbul Özelliği (Admissible) Sezgisel algoritma, en basit anlamda, bir sezgisel algoritmanın, problem bağımlı olarak bazı tahminlerde bulunmasıdır. Örneğin daha önce [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan : Şadi Evren ŞEKER</p>
<p>Bu yazının amacı, <a href="http://www.bilgisayarkavramlari.com/2008/12/22/sezgisel-algoritmalar-bulussal-algoritmalar-heuristic-algorithms/">sezgisel algoritmalar (heuristic algorithms)</a> tarafından kullanılan sezgisel fonksiyon (heuristic function) kavramını açıklamak ve bazı zaviyelerden tasnif etmektir. </p>
<p class="shutter"><a href="#1">1. Baskınlık Özelliği (Dominance)</a><br />
<a href="#2">2. Tutarlılık Özelliği (Consistent, Monotone)</a><br /> <br />
<a href="#3">3. Makbul Özelliği (Admissible)</a> </p>
<p><a href="http://www.bilgisayarkavramlari.com/2008/12/22/sezgisel-algoritmalar-bulussal-algoritmalar-heuristic-algorithms/">Sezgisel algoritma</a>, en basit anlamda, bir sezgisel algoritmanın, problem bağımlı olarak bazı tahminlerde bulunmasıdır. Örneğin daha önce yazdığım <a href="http://www.bilgisayarkavramlari.com/2009/03/02/a-yildiz-arama-algoritmasi-a-star-search-algorithm-a/">A* (A yıldız, A Star) algoritmasında</a>, bir yol bulma örneği vermiştim. Bu algoritmadaki amaç, hedef düğüme (node) en kısa ulaşan yolu bulmaktı. Yollar karışık olmasına karşılık, hedefe giden kuş uçuşu mesafeyi sezgisel bir fonksiyon olarak kabul etmiştik:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/2009/03/astar2.jpg"></p>
<p>Yukarıdaki şekilde, siyah renkle yazılı olan sayılar, düğümler arası mesafeyi gösterirken, düğümlerin üzerinde kırmızı renkle yazılan sayılar, o düğümün, hedefe olan kuş uçuşu mesafesini vermektedir. Bu durumda en kısa yolu bulmayı hedeflediğimiz bu problemde, sezgisel olarak bir fonksiyon tanımlamış oluyoruz ve problem hakkında bir bilgiyi, problemin çözümünde avantaj sağlaması için kullanıyoruz.</p>
<p>Farklı bir problem ve farklı bir fonksiyon tanımı yaparak konuyu daha iyi izah etmeye çalışalım. Örneğin 8 bulmacası (8 puzzle) olarak bilinen, aşağıdaki klasik oyunu ele alalım.</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/8puzzle.png" alt="8puzzle" title="8puzzle.png" border="0" width="600" height="358" /></p>
<p>Yukarıdaki temsili resimde görüldüğü üzere, 8 bulmacasının bir başlangıç durumundan bir hedef durumuna kadar her adımda bir kutuyu boş olan hücreye kaydırmak suretiyle oynanması amaçlanmaktadır. Amacımıza yönelik olarak bir bilgisayar programı geliştirmek için sezgisel algoritmalardan (heuristic algorithms) faydalanmak istiyoruz. Bu durumda kullanabileceğimiz sezgisel algoritmalarda en önemli etkenlerden birisi de sezgisel fonksiyonumuz olacaktır. Yani probleme has bir fonksiyon geliştireceğiz ve bu fonksiyonla her adımda karar vermeye çalışacağız. </p>
</p>
<p>Bu aşamada iki fonksiyondan birisi önerilebilir:</p>
<ul>
<li>Taşların kaç tanesinin yerinde olmadığı</li>
<li>Taşların bitiş durumunda olması gereken yere olan <a href="http://www.bilgisayarkavramlari.com/2007/11/24/kare-uzaklik-sehir-mesafe-uzakligi-taksi-uzakligi-city-block-distance-taxicab-distance/">uzaklığı (kare mesafesi, manhattan distance)</a></li>
</ul>
<p> Yukarıdaki iki farklı fonksiyon için de, yine yukarıda verilen şekildeki mesafeleri hesaplayalım.</p>
<p> ilk fonksiyonumuz olan, yanlış yerdeki taş sayısını hesaplamak için, yerinde olmayan taşları listeleyelim: 1,2,3,4,5,6,7,8 taşlarının tamamı hedef durumda olması gereken yerde değil. Burada boşluk hücresinin konumunu da sayarsak fonksiyon değeri olarak 9 buluruz. </p>
<p>İkinci fonksiyonumuza göre taşların, hedef konumuna olan mesafelerini sırasıyla listeleyelim:</p>
<ol>
<li>3</li>
<li>1</li>
<li>2</li>
<li>2</li>
<li>2</li>
<li>3</li>
<li>3</li>
<li>2</li>
</ol>
<p>Yukarıda, her taşın hedef konumuna olan mesafesi verilmiştir. Daha iyi anlaşılması açısından, örneğin 1 numaralı taş başlangıç durumunda sağ alt köşedeyken, bitiş durumunda üst ortaya gelmesi isteniyor. Bu taşın, tahtada hiç başka taş olmasaydı, başlangıç durumundan hedef durumuna gelebilmesi için yapılan hamle sayısı 3&#8242;tür. Yukarıdaki listede de her taş için bu değer sırasıyla yazılmıştır. </p>
<p>Fonksiyonumuzun toplam değeri : 3+1+2+2+2+3+3+2 = 18 olarak bulunur</p>
<p> Yukarıda, aynı problem için iki farklı sezgisel fonksiyon örneği verdik. Şimdi bu iki fonksiyonu karşılaştırarak özelliklerini açıklamaya çalışalım </p>
<p><b><a name="1"></a>1. Baskınlık ( Dominance ) Özelliği</b></p>
<p>Bu özellik, aynı problemin, aynı algoritma ile sezgisel olarak çözümü sırasında birden fazla fonksiyon bulunuyorsa, bu fonksiyonlar arasında seçim yapma kriterini belirler. Buna göre <a href="http://www.bilgisayarkavramlari.com/2010/05/17/fonksiyonlarin-tersi-inverse-ve-bileskesi-terkibi-composition/">bir fonksiyonun alabileceği değer kumesi (fonksiyonun menzil uzayı (range) ) </a> ne kadar geniş ise o kadar baskın fonksiyondur ve o derecede tercih edilmelidir. </p>
<p>Örneğin yukarıda, 8 bulmacası için iki farklı fonksiyon tanımı yaptık. Bu fonksiyonlardan ilki olan, yanlış yerdeki taş sayısı, en fazla 9 değeri alabilir. Şayet taşlardan bir tanesi doğru yerdeyse, fonksiyon değeri düşerek 8 değerine sahip olacaktr. Dolayısıyla fonksiyonun tanımlı olduğu, ve sonuç olarak döndürebileceği değerler 0 ile 9 arasındadır. </p>
<p>İkinci fonksiyonumuz olan <a href="http://www.bilgisayarkavramlari.com/2007/11/24/kare-uzaklik-sehir-mesafe-uzakligi-taksi-uzakligi-city-block-distance-taxicab-distance/">manhattan mesafesi</a> ise, taşların azami mesafede olması durumunda her taş için ayrı ayrı olarka 4 değerine sahip olabilir. (hedef durumunun (goal state) saat yönünde 4 kere çevrildiğini düşünün) ve 8 taşımız olduğu için 4 x 8 = 32 değeri, fonksiyonun döndürebileceği azami değerdir. Dolayısıyla fonksiyon 0 ile 32 arasındaki herhangi bir değeri döndürebilir. </p>
<p> İki fonksiyon kıyaslandığında, ilk fonksiyonun 9 ihtimalden birisini döndürebildiği, ikinci fonksiyonun ise 32 ihtimalden birini döndürebildiği görülmektedir. Bu durumda, ikinci fonksiyon, ilkine nazaran baskın fonksiyon olmakta ve ikisinden birisinin tercih edilmesi gerektiğinde, ikincisinin tercih edilmesi daha doğru olmaktadır. </p>
<p> Yukarıdaki baskınlık durumunun daha iyi anlaşılması için iki fonksiyon arasındaki farkı anlatmaya çalışalım. Çok kaba anlamda, ikinci fonksiyon 32 farklı değer döndürürken, ilk fonksiyon 9 farklı değer döndürebilmektedir. Bunun anlamı, ikinci fonksiyonun ayırt ettiği bazı durumları, ilk fonksiyonun ayıramamasıdır. Örneğin ilk fonksiyondaki her değer için ikinci fonksiyonda 3-4 farklı değer bulunabilmektedir. Diğer bir deyişle, 9 ihtimalden bir tanesi, 32 ihtimalden bir kaç tanesine karşılık gelmekte, bu bir kaç farklı durum da fonksiyonun sonuca ne kadar yaklaşıldığını ölçmede ayırım oluşturmasını sağlamaktadır. </p>
<p>Daha net bir şekilde farkını anlatacak olursak, bulmacanın verildiği şekildeki, 8 ve 5 numaralı karolar, başlangıç durumunda yer değiştirmiş olsaydı, ilk fonksiyonumuza göre, yerinde olmayan taş sayısı yine 9 olarak bulunacaktı. Ancak ikinci fonksiyonumuzda 18 yerine 20 değeri bulunmuş olunacaktı. Bu değişim, ilk fonksiyona göre karar vermemize imkan tanımazken, ikinci fonksiyon, aralarında seçim yapma imkanı sunacaktı.</p>
<p><a name="2"></a><b>2. Tutarlılık (Consistent, Monotone)</b></p>
<p>Tutarlılık kavramını anlamak için üçgen eşitsizliği halini anlamamız gerekir. Çok basit anlamda, bir üçgenin üç kenarı a b ve c olmak üzere, herhangi iki kenarının toplamı, üçüncü kenardan büyük olmalıdır. Bu hale üçgen eşitsizliği hali denir ve tersten okunursa, herhangi bir kenarın, diğer iki kenarın toplamından küçük olması olarak yorumlanabilir.</p>
<p>Şimdi bu çok basit kavram olan üçgen eşitsizliğinin sezgisel fonksiyonla nasıl bir ilişkisi var diye sorabilirsiniz. Tutarlılık durumu, gayet basittir aslında, basitçe bir arama şeklinde (graph) herhangi bir düğümün aldığı sezgisel fonksiyon değeri, çocuğunun aldığı sezgisel foknsiyon değeri ile toplandığında çıkan sonuç çocuğunun çocğuna doğrudan giden değerden daha büyük olmalıdır. Durumu aşağıdaki şekilde görsel olarak ifade edelim:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/tutarlisezgisel.png" alt="Tutarlisezgisel" title="tutarlisezgisel.png" border="0" width="481" height="296" /></p>
<p>Yukarıdaki şekilde görüldüğü üzere en sağdaki düğüme giden ve n<sub>i</sub> düğümünden başlayan iki yol bulunmaktadır. Bu yollardan birisi doğrudan gitmekte olup, ağırlık değeri (weight) h(n<sub>i</i>) olarak ifade edilmiştir. İkinci yol ise n<sub>j</sub> üzerinden geçen yol olup, önce c(n<sub>i</sub>, n<sub>j</sub>) (n<sub>i</sub> ile  n<sub>j</sub> arasındaki gerçek mesafe (sezgisel değil) ) mesafesi gidilmekte ardından n<sub>j</sub> için sezgisel bir değer bulunmaktadır. İşte üçgen eşitsizliği, bu iki değer arasında, ikincisinin daha büyük olmasını gerektirir. Ki bu durum, yukarıdaki şekilde de aşağıdaki şekilde ifade edilmiştir:</p>
<p> h(n<sub>i</sub>) &lte; c(n<sub>i</sub>, n<sub>j</sub>) + h(n<sub>j</sub>)</p>
<p> Şayet bir sezgisel fonksiyon yukarıdaki bu şartı her durum için sağlıyorsa tutarlı (consistent) sağlamıyorsa tutarsız (inconsistent) olarak tasnif edilebilir. </p>
<p> Fonksiyonların, tutarlı olması tercih edilir bir durumdur, bunun sebebi bir düğümden diğerine gidildiğinde ödenen maliyetin sezgisel fonksiyona yansımasının, sonucu bulmada etkisi olmasıdır. Şayet bir fonksiyon tutarsız ise, mesafe giderken harcanan maliyetin, sezgisel fonksiyona yansımadığı, en az bir durum var demektir ki bu da problemin çözümünde sorunlarla karşılaşılmasını (en azından tutarlı bir fonksiyona göre daha geç sonucun bulunmasını) beraberinde getirir.
</p>
<p>Tutarlı bir fonksiyonun, aynı zamanda tektonlu (monotone) olarak isimlendirilmesinin sebebi ise, yukarıda izah edildiği üzere bir fonksiyonun tutarlı olması halinde, her düğümün tek bir kere ziyaret edilmesidir. Şayet bir fonksiyon tutarsız ise (inconsistent) bu durumda, aynı düğüm, arama işlemi sırasında, birden fazla kere ziyaret edilebilir. İşte bu anlamda tutarlı fonksiyonlar aynı zamanda tektonlu (monotone) olarak isimlendirilir.</p>
<p><b><a name="3"></a>3. Makbul (Macaiz, Kabul Edilebilir, Admissable)</b></p>
<p>Literatürde admissable olarak geçen durumdur. Bir sezgisel algoritmanın kabul edilebilir olup olmadığını (makbul) belirler. Makbul, hali, kısaca bir sezgisel fonksiyonun, herhangi bir mesafe için, gerçek mesafeden her zaman daha küçük değer vermesidir. Örneğin herhangi bir düğüm n için gerçek mesafe f(n) iken sezgisel fonksiyon olan h(n) değeri, her zaman için h(n) &lte; f(n) şartını sağlamalıdır</p>
<p>Şayet bütün düğümler, yukarıdaki bu h(n) &lte; f(n) şartını sağlıyorsa, bu sezgisel fonksiyona makbul (admissible) ismi verilebilir. Şayet sağlamayan tek bir durum varsa, bu sezgisel fonksiyonun makbul olmadığını (gayri makbul, non-admissible) söyleyebiliriz. </p>
<p>Yukarıdaki bu yaklaşımın sebebi, gerçek değerden daha yüksek bir sezgisel değer elde edildiği anda, bu sezgisel değerin, en iyi çözüm olan gerçek değeri perdelemesidir. Yani bir sezgisel algoritmada, makbul olmayan bir sezgisel fonksiyon kullanılırsa, bu fonksiyon için, sezgisel algoritmamız en iyi çözümü bulamayabilir.</p>

<p class="sayac_bilgi">335 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/11/13/sezgisel-fonksiyonlar-heuristic-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yinelemeli Derinlik Araması (Iterative Deepining Search)</title>
		<link>http://www.bilgisayarkavramlari.com/2011/11/08/yinelemeli-derinlik-aramasi-iterative-deepining-search/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/11/08/yinelemeli-derinlik-aramasi-iterative-deepining-search/#comments</comments>
		<pubDate>Tue, 08 Nov 2011 17:12:13 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[graf teorisi (graph theory, çizge kuramı)]]></category>
		<category><![CDATA[veri yapıları]]></category>
		<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/?p=5983</guid>
		<description><![CDATA[Yazan :Şadi Evren ŞEKER Bilgisayar bilimlerinin çeşitli alanlarında (örneğin yapay zeka, veri yapıları veya şekil kuramı (graph theory) gibi) kullanılan arama algoritmalarından birsidir. &#160; Algoritma, derin öncelikli drama (depth first search) üzerine kurulu olduğu için, literatürde &#8220;iterative deepening depth first search (yinelemeli derinleşen, derin öncelikli arama)&#8221; olarak da geçmektedir. &#160; Algoritma basitçe derinlik değerini bir [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan :Şadi Evren ŞEKER</p>
<p>Bilgisayar bilimlerinin çeşitli alanlarında (örneğin yapay zeka, veri yapıları veya şekil kuramı (graph theory) gibi) kullanılan arama algoritmalarından birsidir.</p>
<p>&nbsp;</p>
<p>Algoritma, <a href="http://www.bilgisayarkavramlari.com/2008/11/13/derin-oncelikli-arama-depth-first-search/">derin öncelikli drama (depth first search) </a>üzerine kurulu olduğu için, literatürde &#8220;iterative deepening depth first search (yinelemeli derinleşen, derin öncelikli arama)&#8221; olarak da geçmektedir.</p>
<p>&nbsp;</p>
<p>Algoritma basitçe derinlik değerini bir değişkende tutmakta ve bu değeri her adımda arttırmaktadır.<br />
Yineleme yapısı (iteration) basit bir döngü (loop) olarak düşünülebilir ve her adımda derinliğin, bir döngü değişkeni (loop variable) gibi düşünülerek derinleştiği kabul edilebilir.</p>
<p>&nbsp;</p>
<p>Örneğin aşağıdaki şekli (graph) ele alalım:</p>
<p>&nbsp;</p>
<p><img title="cyclictree.png" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/cyclictree.png" alt="Cyclictree" width="361" height="221" border="0" /></p>
<p>Ağaçta görüldüğü üzere iki adet <a href="http://www.bilgisayarkavramlari.com/2008/08/01/basit-dongu-simple-cycle/">döngü (cycle)</a> bulunmaktadır. Iterative Deepening search algoritmasını bu ağaç üzerinde çalıştıracak olursak, algoritma öncelikle derinlik değerini (bundan sonra d değişkeni (variable) ile ifade edilecektir) 0&#8242;dan başlatarak her adımda bir ilerletecektir.</p>
<p>d=0 için arama:<br />
A<br />
d=1 için arama:<br />
A (tekrar A değerine bakar) B C (sanki ağacın en üstteki üç düğümü, şekilde gösterildiği gibi bağlanmış kabul edilebilir, daha alttaki derinliklerde bulunan DEFG düğümlerine hiç bakamaz)<br />
d=2 için arama:<br />
A B D E C F G (Bu aramada sanki sondaki daireler (cycle) bulunmuyormuş gibi kabul edilebilir, çünkü belirtilen derinlik bu dairelere kadar inemez)<br />
d=3 için arama:<br />
A B D B E C F G A<br />
d=4 için arama:<br />
A B D B D E B C F G A B C</p>
<p>Yukarıdaki arma işlemi, derinlik arttıkça devam etmektedir.</p>
<p>&nbsp;</p>
<p>Arama algoritmalarının değerlendirildiği bazı kriterler bulunmaktadır. Buna göre IDDFS (iterative deepening depth first search) algoriması &#8220;tam&#8221; algoritma olarak kabul edilebilir.<br />
<strong>Tamlık teriminin (completeness)</strong> anlamı aşağıdaki şekilde tanımlanabilir:</p>
<p>Bir arama algoritması, bütün düğümleri dolaşarak aranan düğümü bulmayı garanti ediyorsa bu algoritmaya tam arama algoritması ismi verilir.</p>
<p>Örneğin yine yukarıdaki şekil için klasik derin öncelikli arama (depth first search) algoritmasını ele alsaydık, bu algoritmanın tam olmadığını söyleyebilirdik. Bunun sebebi DFS algoritmasının dolaşması sırasında, aşağıdaki döngüye girmesidir:</p>
<p>A B D B D B D ( B D ikilisi sosuza kadar tekrar eder)</p>
<p>Kısacası A B D düğümleri dışındaki düğümlere asla bakmaz. Bu anlamda tam olmadığını söyleyebiliriz.</p>
<p><a href="http://www.bilgisayarkavramlari.com/2008/11/13/sig-oncelikli-arama-breadth-first-search/">BFS (breadth first search , yayılma öncelikli veya sığ öncelikli arama)</a> algoritması ise her zaman için tam kabul edilebilir, sebebi bir sonraki derinlik seviyesine inmeden önce, bulunduğu seviyedeki düğümleri bitirmesi ve bu sayede bütün ağaca bakmayı garanti etmesidir.</p>
<p><strong>Algoritmanın karmaşıklığına</strong> değinecek olursak. Aşağıdaki şekilde bir formül ile karşılaşırız.</p>
<p><img title="iddscompleks.png" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/iddscompleks.png" alt="Iddscompleks" width="454" height="27" border="0" /></p>
<p>Bu formülde görülen terimler şekil kuramında (graph theory) sıkça kullanılan bazı değerlere atıfta bulunur.<br />
d değerinin derinlik olduğunu daha önce belirtmiştik. b ile gösterilen değer ise dallanma katasyısıdır (branching factor).</p>
<p>Kısaca her<a href="http://www.bilgisayarkavramlari.com/2009/06/18/dugum-derecesi-order-of-node/"> düğümün kaç çocuğu olduğu (out order, kaç düğüme gidilebildiği)</a> olarak tutulur. Örneğin tam dolu <a href="http://www.bilgisayarkavramlari.com/2008/05/07/ikili-arama-agaci-binary-search-tree/">ikili arama ağacının (binary search tree)</a> b değeri 2&#8242;dir. Genelde en kötü durum analizinde bütün çocukların dolu olması ihtimali üzerinde durulur. Ayrıca istatistiksel olarak ortalamam çocuk sayısının da alındığı olur. Örneğin şehirlerin tutulduğu bir şekilde, her şehirden gidilebilecek şehir sayısı değişmektedir. Bu durumda b değeri ortalama değer olarak hesaplanabilir.</p>
<p>&nbsp;</p>
<p>Bu açıklama ardından yukarıdaki denkleme tekrar bakarak anlamaya çalışalım.</p>
<p>&nbsp;</p>
<p>IDDFS algoritmasında, en altta bulunan düğümlerin 1 kere (d sabitlendiğinde en altta kalan düğümler hangileri ise) dolaşıldığını, d-1 derinliğindeki düğümlerin ise 2 kere dolaşıldığını ve böylece <a href="http://www.bilgisayarkavramlari.com/2008/05/07/agaclar-tree/">kök düğüme (root)</a> kadar her düğümün, bulunduğu seviyeye göre kaç kere dolaşıldığını hesaplayabileceğimize göre yukarıdaki denklem çıkarılabilir.</p>
<p>&nbsp;</p>
<p>Diğer bir deyişle d=0 için kök 1 kere dolaşılırken d=1 olduğunda kök 2 ve kökün çocukları 1 kere dolaşılmış olur. d=3 olduğunda kök 3 kere ve çocukları 2 ve en alttaki çocuklar ise 1 kere dolaşılmış olur. Görüldüğü üzere derinliğin her artışında kök derinlik kadar altındaki her düğüm ise birer azalarak en nihayetinde<a href="http://www.bilgisayarkavramlari.com/2008/05/07/agaclar-tree/"> yapraklar (leaf)</a> tek bir kere dolaşılmış olmaktadır.</p>
<p>&nbsp;</p>
<p>Sonuç olarak Yukarıdaki formülün ilk terimi kök (d+1)1 (tek düğüm d+1 kere dolaşılmıştır) , ikinci terimi kökün çocukları (db (kökün çocukları (ki sayısı b&#8217;dir) derinlik kadar (ki d ile gösterilir) dolaşılmıştır).</p>
<p>&nbsp;</p>
<p>Yukarıdaki bu formülü daha toplu şekilde aşağıda gösterildiği gibi yazabiliriz:<br />
<img title="iddskompleks2.png" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/iddskompleks2.png" alt="Iddskompleks2" width="132" height="62" border="0" /></p>
<p>&nbsp;</p>
<p>Algoritmanın dolaşma (arama) zamanı karmaşıklığı yukarıda gösterildiği gibidir. Terimler birleştirildiğinde<a href="http://www.bilgisayarkavramlari.com/2008/12/22/en-kotu-durum-analizi-worst-case-analysis/"> en kötü durum analizi (worst case analysis) </a>için O(b<sup>d</sup>) gösterimi kullanılabilir.</p>
<p>&nbsp;</p>
<p>Hafıza karmaşıklığı ise O(bd) olarak ifade edilebilir. Bunun sebebi d derinliğindeki bir ağacın her seviyesinde b adet çocuğu bulunması durumunda bd kadar düğüm olacağıdır. Algoritma, çalışması sırasında ilave düğümlere ihtiyaç duymaz ve şeklin kendisi üzerinde dolaşarak sonuca ulaşır.</p>

<p class="sayac_bilgi">387 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/11/08/yinelemeli-derinlik-aramasi-iterative-deepining-search/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Labirentte yol bulma kodu</title>
		<link>http://www.bilgisayarkavramlari.com/2011/11/04/labirentte-yol-bulma-kodu/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/11/04/labirentte-yol-bulma-kodu/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 21:12:29 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[JAVA]]></category>
		<category><![CDATA[veri yapıları]]></category>
		<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/2011/11/04/labirentte-yol-bulma-kodu/</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Bu yazının amacı, geri izleme algoritmasının (backtracking algorithm) bir uygulaması olarak, basit bir labirentte yol bulma kodunu JAVA dilinde kodlamaktır. Bu uygulamada herhangi bir yapay zeka yönetmi uygulanmayacaktır. Basitçe kör arama (blind search) yapan ve ihtimalleri sırayla deneyen bir robot uygulaması geliştirilecektir. Örneğin labirent bilgisinin bir dosyada bulunduğunu ve bizim [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan : Şadi Evren ŞEKER</p>
<p>Bu yazının amacı, <a href="http://www.bilgisayarkavramlari.com/2009/11/01/geri-izleme-algoritmasi-backtracking-algorithm/">geri izleme algoritmasının (backtracking algorithm)</a> bir uygulaması olarak, basit bir labirentte yol bulma kodunu JAVA dilinde kodlamaktır. Bu uygulamada herhangi bir yapay zeka yönetmi uygulanmayacaktır. Basitçe kör arama (blind search) yapan ve ihtimalleri sırayla deneyen bir robot uygulaması geliştirilecektir.</p>
<p>Örneğin labirent bilgisinin bir dosyada bulunduğunu ve bizim amacımızın bu dosyayı okuyarak labirentin başlangıcından çıkışına kadar olan yolu bulmak olduğunu düşünelim. Labirent tasarımımızda duvarları 1 ve yolları 0 ile gösterelim. Örneğin aşağıda bir labirent verilmiştir:</p>
<p>1111111<br />
0010011<br />
1000011<br />
1101111<br />
1100000<br />
1111111</p>
<p>Yukarıdaki bu labirentte, sol üst köşeyi başlangıç konumu ve sağ alt köşeyi de bitiş konumu olarak kabul edeceğiz. Buna göre labirentin her zaman için ikinci satırının ilk kolonunda başlıyoruz ve labirentin boyutuna göre son satırın bir üstünde en sağ kolonda bitiriyoruz. Amacımız bu iki nokta arasındaki yollardan bir tanesini çözüm olarak bulmak. Ayrıca dosyadan labirent okuyacağımız için, veri yapısı kullanımını kolaylaştırmak amacıyla, labirentin boyutlarını da dosyanın ilk satırında tutalım. Buna göre bir labirent dosyasının içeriği aşağıdaki şekilde olacaktır:</p>
<p>6 7<br />
1111111<br />
0010011<br />
1000011<br />
1101111<br />
1100000<br />
1111111</p>
<p>Dosyanın ilk satırında, labirentin satır ve sütun boyutları verilmiştir.</p>
<p>Algoritmamız, basitçe labirentin başlangıç konumundan yola çıkacak ve yol alternatiflerini değerlendirecektir. Şayet yol tek yönlü ise hareket etmeye devam edecek ancak bir yol ayrımına geldiğinde bu noktayı bir <a href="http://www.bilgisayarkavramlari.com/2007/05/04/stack-yigin/">yığında (stack)</a> tutarak çıkmaz bir yola girdiğinde en son aklında tuttuğu bu yola geri dönecek ve farklı bir karar verecektir.</p>
<p>Örneğin yukarıdkai problem için çözümü elle yaparak tasarımımıza başlayalım. Başlangıç durumumuz (1,0) olacak (dizide satır sayısının 0&#8242;dan başladığını düşünürsek, ikinci satırın ilk sütunu (1,0) olarak gösterilecektir.</p>
<p>Bitiş durumumuz ise (4,6) olarak belirlenecektir (dizi boyutumuzda azami satır ve sütun değerleri 5,6 olacaktır (boyuttan bir eksik) ve en altın bir üstü satır 4 ve son sütun 6 olacaktır. Dolayısıyla bitiş durumu olarak (4,6) tanımlıyoruz.</p>
<p>(1,0) konumundan, (4,6) konumuna kadar olan çözüm yolunu bulmak için adım adım algoritma tasarımımızı inceleylim.</p>
<p>Algoritmamız kör arama (blind search) olduğu için, çözüme giden en mantıklı yolu bulmak yerine bütün ihtimalleri deniyeceğiz. Bu ihtimalleri belirli bir sıra ile aramamız gerekiyor. Bu srıalama için algoritmamızı aşağıdaki şekilde tasarlayalım:</p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>Geldiğim yeri işaretle</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>if(sola gidilmemişse)</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>sola git;</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>else if(sağa gidilmemişse</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>sağa git;</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>else if(yukarı gidilmemişse)</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>yukarı git;</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>else if (aşağı gidilmemişse)</em><br />
</span></p>
<p><span style="font-family: Times New Roman; font-size: 12pt;"><em>aşağı git;</em><br />
</span></p>
<p>Yukarıdaki bu tasarımda sol -&gt; sağ -&gt; yukarı -&gt; aşağı sırası tamamen rast gele olarak üretilmiştir ve daha farklı sırada da olabilirdi.</p>
<p>(1,0) konumundan başlayarak yukarıdaki algoritmayı icra ettirelim. İşaretleme için 2 değerini kullanacağız. Öncelikle <a href="http://www.bilgisayarkavramlari.com/2007/05/04/stack-yigin/">yığın (stack)</a> değeri boş olarak başlıyoruz (bundan sonra S olarak gösterilecek ve sağdan eklenerek sağdan çıkarma yapılacaktır):</p>
<p>1111111<br />
0010011<br />
1000011<br />
1101111<br />
1100000<br />
1111111</p>
<p>S -&gt; boş</p>
<p>İlk değeri işaretliyoruz:</p>
<p>1111111<br />
2010011<br />
1000011<br />
1101111<br />
1100000<br />
1111111</p>
<p>(1,0) konumunda tek gidilebilecek komşu, (1,1) konumudur (1,0) konumunun komşuları 0,0 2,0 ve 1,1 olduğuan göre bu değerlere bakıyoruz ve bunlardan 0 olan tek değere gidiyoruz:</p>
<p>1111111<br />
2210011<br />
1000011<br />
1101111<br />
1100000<br />
1111111</p>
<p>Benzer şekilde (1,1) konumunun tek 0 olan komşusu (2,1) olan konuma gidiliyor. Benzer şekilde (2,1) konumunun tek komşusu olan (2,2) konumuna gidilerek aşağıdaki durum elde ediliyor:</p>
<p>1111111<br />
2210011<br />
1220011<br />
1101111<br />
1100000<br />
1111111</p>
<p>Yukarıdaki son durumda geldiğimiz konum (2,2) ve birden fazla komşumuzda 0 değer var. Yani (2,2) konumunun komşuları olan (2,3) ve (3,2) değerleri 0 olduğu için bu alternatiflerden birisini takip edeceğiz. İşte bu yol ayrımında yığın (stack) kullanmanın sırası geliyor. Bunun sebebi şu anda vereceğimiz kararın doğru olup olmadığını bilmediğimiz ve basitçe hata yapıyorsak buraya geri dönmek istememiz.</p>
<p>S -&gt; (2,2)</p>
<p>Yukarıdaki şekilde karar noktamızı yığına yerleştirdikten (push) sonra algoritmamızdaki öncelikli yol olan sol tarafı deniyoruz. Sol tarafımızda ((2,2)&#8217;nin solunda (2,1) vardır) 0 olmadığı için gidemiyoruz. Algoritmamızdaki ikinci ihtimal olan sağ tarafa bakıyoruz (sağın koordinatı (2,3)) ve bu değer 0 olduğu için bu yönde gidiyoruz.</p>
<p>1111111<br />
2210011<br />
1222011<br />
1101111<br />
1100000<br />
1111111</p>
<p>Sağa gitme işlemine devam ediyoruz (aşağıya gidemediğimiz için) ayrıca burada bir yol ayrımı bulunduğu için (sağa veya yukarıya gidebiliriz) yığının (stack) içerisine yerleştiriyoruz:</p>
<p>S -&gt; (2,2) , (2,3)</p>
<p>1111111<br />
2210011<br />
1222211<br />
1101111<br />
1100000<br />
1111111</p>
<p>Tek alternatif olan yukarıya devam ediyoruz:</p>
<p>1111111<br />
2210211<br />
1222211<br />
1101111<br />
1100000<br />
1111111</p>
<p>Tek alternatif olan sola devam ediyoruz:</p>
<p>1111111<br />
2212211<br />
1222211<br />
1101111<br />
1100000<br />
1111111</p>
<p>Netice itibariyle alternatifi kalmayan (hiçbir yönde 0 olmayan) bir duvar ile karşılaştık ve bu noktadan sonra çıkma ihtimalimiz kalmadığı için yığındaki en üstte bulunan ve en son karar verdiğimiz noktaya dönüyoruz.</p>
<p>Bu nokta (2,3) koordinatlarındadır ve pop edildikten sonra stack aşağıdaki şekildedir:</p>
<p>S &#8211; &gt; (2,2)</p>
<p>Pop ettiğimiz (2,3) noktasında da gidilecek hiçbir alternatif bulunmuyor. Mecburen yığındaki (stack) bir sonraki noktaya dönüyoruz:</p>
<p>S -&gt; Boş</p>
<p>Döndüğümüz koordinat (2,3) noktası ve buradaki tek alternatif aşağı yönde bulunan 0 değeri:</p>
<p>1111111<br />
2212211<br />
1222211<br />
1121111<br />
1100000<br />
1111111</p>
<p>Bu aşamadan sonra, hiçbir alternatif kalmadan 0 olan yollar izlenerek sonuca ulaşan yol bulunmuş oluyor.</p>
<p><strong>Kodlama<br />
</strong></p>
<p>Yukarıdaki yaklaşımın JAVA dilinde kodlanmış hali yazının sonunda verilmiştir. Bu kodun kısaca açıklamasını bu bölümde anlatacağım. Kodumuzda temel olarak iki sınıf bulunuyor:</p>
<ul>
<li>currentInfo</li>
<li>Maze</li>
</ul>
<p>currentInfo sınıfı, anlık olarak matrisin hangi konumunda bulunduğumuzu tutmaya yarıyor. Çok basit şekilde satır ve sütün koordinatlarımızı barındırıyor. Ayrıca bu değerlere erişmeyi sağlayan <a href="http://www.bilgisayarkavramlari.com/2008/11/24/yapici-constructor/">inşa sınıfları (constructors)</a> ve <a href="http://www.bilgisayarkavramlari.com/2010/10/25/c-dili-ile-kapsulleme-encapsulation/">kapsülleme fonksiyonları (encapsulation)</a> bulunuyor.</p>
<p>Maze sınıfı ise geri kalan herşeyi yapan ana sınıfımız. Bu sınıfta getMaze() isimli fonksiyon, dosyadan labirent bilgilerini okumak için kullanılıyor. solveMaze fonksiyonu da labirentteki sonucu bulmaya yarayan yukarıdaki işlemleri çalıştırıyor.</p>
<p>Yukarıdaki anlatımda geçen ve S harfi ile ifade ettiğimiz <a href="http://www.bilgisayarkavramlari.com/2007/05/04/stack-yigin/">yığın (stack)</a> ise kodumuzda path ismi ile tanımlanmış java.util.Stack sınıfından tanımlanmış bir yığın. Buradaki yığın, karar verirken atılan her adımı tutmakta. Yani yukarıdaki labirent çözümünde geçen ve 2 olarak işaretlerken, birden fazla 0 ihtimali bulunan dönüm noktalarını tutuyor.</p>
<p>Yığının en temel 3 fonksiyonu ise aşağıdaki şekildedir:</p>
<ul>
<li>Pop() yığında bulunan en üstteki değeri alarak bir değişkene döndürür.</li>
<li>Push() yığının en üstüne, parametre olarak aldığı veriyi yerleştirir.</li>
<li>Peek() yığının en üstündeki veriyi alır ancak pop fonksiyonunun aksine bu veriyi silmez. Bu fonksiyon bazı kaynaklarda Top() olarak da geçmektedir ancak java.util.Stack sınıfında peek ismi ile tanımlanmıştır.</li>
</ul>
<p>Kodumuzda kullandığımız iki temel dizi ise aşağıda verilmiştir:</p>
<ul>
<li>mazeData[][] iki boyutlu bu dizi, dosyadan okunan ve hafızada labirent bilgisini tutan dizidir.</li>
<li>Mark[][] diğer iki boyutlu dizimiz ise sonuca giden yolu tutar.</li>
</ul>
<p>İkinci diziye neden ihtiyaç duyduğumuz sorusunu şu şekilde cevaplayalım. Dizimizi dolaşırken, yanlış yollara sapabiliyoruz, geçtiğimiz her yeri basarsak bu sonuçta görmek istediğimiz çözüm yolu olmayacaktır. Ayrıca labirentte dolaşırken, çözüme giden yolu 2 ile işaretliyoruz ama hatalı yolları da 2 ile işaretliyoruz. Dolayısıyla labirenti dolaştıktan sonra 2 ile işaretli yolları basarsak bu yollarda da sonuca gitmeyen değerlerin basılması söz konusu. Çözüm olarak ayrı bir dizide, sonuca giden yoldaki koordinatları ayrıca tutuyoruz.</p>
<p>Koddaki bazı satırları anlatmamız gerekirse:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/110311_2112_Labirenttey1.png" alt="" /></p>
<p>Yukarıdaki kod parçasında, bulunduğumuz konumdan (current) sonraki gidebileceğimiz yönleri sırasıyla deniyoruz. İlk if koşulunda mazeData isimli dizide (yani labirentin verilerinin tutulduğu dizi) bulunan ve mevcut konumun bir sağında yer alan (col + 1 işleminin anlamı bir sonraki kolon demektir) değere gidilmesi ve bu değerin daha önce mark dizisinde işaretlenmemiş olması (gidilmemiş olması ) durumu kontrol edilmektedir. Ardından sırasıyla, sol, aşağı ve yukarı yönler için aynı kontroller yapılmaktadır. Yazıda anlatılan sıradan bu anlamda farklıdır.</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/110311_2112_Labirenttey2.png" alt="" /></p>
<p>Yukarıdaki kod parçasında ise, bir önceki kod parçasının devamı niteliğinde, şayet 4 yöndede hareket edilemiyorsa, çıkmaz bir yola girilmiş neticesine varılabilir. Bu durumda mevcut durum dolaşıldı anlamında, 2 ile işaretlendikten sonra, yığından (stack) pop fonksiyonu ile dönülecek en son karar anına bakılıyor.</p>
<p>Şayet yığın bir şekilde boş olursa (ki bu durum try/catch blokları arasında <a href="http://www.bilgisayarkavramlari.com/2008/11/22/istisna-yakalama-kabz-i-istisna-exception-handling/">istisna kabz edilerek (exception handling)</a> çözülmüştür) bu durumda labirentin bir çözümü olmadığını söyleyebiliriz çünkü hem bir çıkmaz yol bulduk hem de geriye döneceğimiz hiçbir yol ayrımı bulunmuyor demektir.</p>
<p>Netice itibariyle, 61. Satıra kadar ulaştıysak, bu satırda flag değişkeni true değerinde olup, yukarıdaki 4 iften birisine girerek bir yöne hareket etmiş olabilir. Bu durumda gidilen bu yok, mark dizisinde işaretlerenerek yığına yerleştiriliyor. Ayrıca flag değişkenin false olduğu tek ihtimal olan çıkmaz yol durumunda da if bloğu çalışmıyor.</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/110311_2112_Labirenttey3.png" alt="" /></p>
<p>Yukarıda alıntılıanan kod parçası ise bütün işlemler bitip, labirent bir sonuca ulaşacak şekilde dolaşıldıktan sonra, mark dizisi üzerinden dolaşılan yolu ekrana basmaktadır. Döngü, labirent boyutları olan dim1 ve dim2 sınırlarında dönmekte, her adımdaki konum 71. Satırda ekrana basılmakta ve sonraki konum da 4 farklı koşul konrolü ile işaretlenmiş olan yöne doğru değiştirilmektedir.</p>
<p>Kodun çalışması sonucunda, örnek ekran çıktısı aşağıda verilmiştir:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/110311_2112_Labirenttey4.png" alt="" /></p>
<p>Görüldüğü üzere labirentteki bütün yolları dolaşarak, sonuca ulaşan yolları ekrana basmıştır(lütfen basma işlemi sırasında, 71. Satırda olduğu üzere önce satır sonra sütun koordinatının basıldığına dikkat ediniz). Bu örnek çalışma, aşağıdaki labirent içindir:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/110311_2112_Labirenttey5.png" alt="" /></p>
<p>Ayrıca farklı bir dosya içeriği, projenin bulunduğu dizindeki maze.dat dosyasının içerisine yerleştirilerek çalıştırılabilir.</p>
<p><a href="http://www.bilgisayarkavramlari.com/wp-content/uploads/2011/labirent.rar"><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/110311_2112_Labirenttey6.png" alt="" /><br />
Kodun tamamını netbeans projesi olarak indirmek için tıklayınız.</a></p>

<p class="sayac_bilgi">934 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/11/04/labirentte-yol-bulma-kodu/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Işın Araması (Beam Search)</title>
		<link>http://www.bilgisayarkavramlari.com/2011/11/03/isin-aramasi-beam-search/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/11/03/isin-aramasi-beam-search/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 19:22:48 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[yapay zeka (artificial intelligence)]]></category>
		<category><![CDATA[beam searc]]></category>
		<category><![CDATA[global search]]></category>
		<category><![CDATA[Heuriscit]]></category>
		<category><![CDATA[local search]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/?p=5964</guid>
		<description><![CDATA[Yazan: Şadi Evren ŞEKER Bu yazının amacı, özellikle yapay zeka çalışmaları altında yer alan sezgisel arama algoritmalarının (heuristic search algorithms) bir çeşidi olan ışın araması konusunu anlatmaktır. Işın arması &#8220;en iyi ilk arama&#8221; (best first search) tipi arama algoritmalarındandır ve amacı hafıza ihtiyacını azaltmaktır. En iyi ilk arama yaklaşımını kullanan arama algoritmaları, arama yaptıkları şekil [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan: Şadi Evren ŞEKER<br />
Bu yazının amacı, özellikle yapay zeka çalışmaları altında yer alan <a href="http://www.bilgisayarkavramlari.com/2008/12/22/sezgisel-algoritmalar-bulussal-algoritmalar-heuristic-algorithms/">sezgisel arama algoritmalarının (heuristic search algorithms)</a> bir çeşidi olan ışın araması konusunu anlatmaktır.<br />
Işın arması &#8220;en iyi ilk arama&#8221; (best first search) tipi arama algoritmalarındandır ve amacı hafıza ihtiyacını azaltmaktır. <bR><br />
En iyi ilk arama yaklaşımını kullanan arama algoritmaları, arama yaptıkları şekil (graph) üzerinde bütün çözüm ihtimallerini belirli bir sezgisel fonksiyona göre sıralarlar. Diğer bir deyişle arama işlemi sırasında sezgisel bir fonksiyona göre, aramada bazı kararlara öncelik verirler. Bu sezgisel fonksiyonun amacı, karar anında verilen kararın, sonuç durumuna (goal state) ne kadar yakın olduğunu yargılayabilmektir. <br />
Işın aramasının bir özelliği de, daha önceden belirlenmiş ve sınırlı sayıdaki, yapmış olduğu seçimleri saklamasıdır. <br />
Işın araması, bir arama ağacı (search tree) oluştururken, <a href="http://www.bilgisayarkavramlari.com/2008/11/13/sig-oncelikli-arama-breadth-first-search/">sığ öncelikli arama (breadth first search)</a> yaklaşımı kullanır. buna göre ağacın herhangi bir seviyesinde, gidilebilecek düğümlerin sezgisel değerlerini hesaplar ve bunlardan sadece belirli sayıdaki düğümü, daha sonra geri dönülmek üzere hafızasında tutar. Bu değere ışın aramasına özgü olarak ışın genişliği (beam width) ismi verilir. <br />
Işın genişliği arttıkça daha fazla düğüme bakılmaktadır. Işın genişliği azaldıkça da daha fazla düğüm budanmaktadır (prunning). Budama işleminin dez avantajı, şanssız bir şekilde en iyi sonucu verecek düğüme giden yolu budama riskidir. Ancak bu riskten dolayı bütün düğümleri tutmak (yani hiçbir düğümü budamamak) gibi bir karar verirsek, bu karar sonucunda da çok daha fazla hafıza ve işlem ihtiyacımız olacaktır. İşte ışın araması, bu iki karar arasında en iyi (optimum) noktayı bulmayı amaçlar. <br />
Bu amaca yönelik olarak, ışın araması sabit ışın genişliği (fixed beam width) veya değişken ışın genişliği (variable beam width) kullanacak şekilde kodlanabilir. Değişken ışın genişliği alan arama algoritmasında, öncelikle ışın genişliği asgari değerde tutularak arama yapılır. Aranan en iyi sonuca ulaşılamazsa, ışın genişliği arttırılarak arama işlemi sürdürülür. Beklenen sonuca ulaşılana kadar da ışın genişliği arttırılır.<br />
<br />
Işın aramasının kullanıldığı yerlerden birisi de bilgisayarlar tarafından otomatik olarak yapılan tercüme işlemleridir. Bilindiği üzere bir kelime, bilgisayar tarafından işlendiğinde, birden fazla anlama gelebilmektedir. İnsanlar kelimenin kullanımından (<a href="http://www.bilgisayarkavramlari.com/2009/06/17/sozdizim-syntax/">syntax</a>, <a href="http://www.bilgisayarkavramlari.com/2009/06/15/pragma-edimbilim-kullanimbilim-fiili-ameli/">pragma</a>) kelimenin anlamını kısa sürede doğru olarak anlayabilmekte ancak bilgisayarlar için bu anlama süreci ve doğru anlamın bulunması (semantics), hatırı sayılır bir süre almaktadır. <br />
Çözüm olarak ışın araması algoritması, çok sayıdaki çeviri ihtimallerinden sadece belirli bir kısmını işleyerek doğru tercümeyi yapmak için kullanılabilir.</p>

<p class="sayac_bilgi">158 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/11/03/isin-aramasi-beam-search/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WEKA ile SVM</title>
		<link>http://www.bilgisayarkavramlari.com/2011/09/19/weka-ile-svm/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/09/19/weka-ile-svm/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 05:38:22 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/2011/09/19/weka-ile-svm/</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Bu yazının amacı, site üzerinde gelen bir soru üzerine, WEKA programı üzerinde, destekçi vektör makinesinin (SVM) gerçekleştirilmesi ile ilgili bir uygulama anlatmaktır. WEKA üzerinde genel olarka bir işlem yapmak için aşağıdaki adımlar izlenebilir: Yukarıdaki adımlara göre, öncelikle, işlenmek için hazır bir veri kümemiz bulunması gerekiyor. Yazımızdaki amacımız, konuyu öğrenmek olduğu [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan : Şadi Evren ŞEKER</p>
<p>Bu yazının amacı, site üzerinde gelen bir soru üzerine, <a href="http://www.bilgisayarkavramlari.com/2009/06/01/weka/">WEKA programı</a> üzerinde, <a href="http://www.bilgisayarkavramlari.com/2008/12/01/svm-support-vector-machine-destekci-vektor-makinesi/">destekçi vektör makinesinin (SVM)</a> gerçekleştirilmesi ile ilgili bir uygulama anlatmaktır.</p>
<p>WEKA üzerinde genel olarka bir işlem yapmak için aşağıdaki adımlar izlenebilir:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM1.png" alt="" /></p>
<p>Yukarıdaki adımlara göre, öncelikle, işlenmek için hazır bir veri kümemiz bulunması gerekiyor.</p>
<p>Yazımızdaki amacımız, konuyu öğrenmek olduğu için, WEKA kurulumu ile gelen örnek veri kümelerinden birsini, bu yazı kapsamında kullanacağız.</p>
<ol>
<li><strong>Adım:</strong> WEKA&#8217;yı açıyoruz:</li>
</ol>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM2.png" alt="" /><strong></strong></p>
<p><strong>2. Adım:</strong> Önce veri kümemize bir göz atalım. WEKA&#8217;nın kurulumu ile birlikte gelen data dizini altındaki, labor.arff dosyasını görmek için, açılan ilk weka ekranında (yukarıdaki resimde temsil edilen), &#8220;Experimenter&#8221; düğmesine basıyoruz. Açılan ekranda, File / Open seçeneklerini menülerden seçtikten sonra, dosya seçicisinden &#8220;labor.arff&#8221; dosyasını işaretleyip açıyoruz:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM3.png" alt="" /></p>
<p>Kullanacağımız örnek veri kümesi yukarıdaki şekildedir. Hızlı bir bakışla, verilerin, çalışan verileri olduğunu ve her çalışanın maaş, çalışma süreleri, sosyal güvenliğine ait bilgilerin yer aldığı bir veri kümesi olduğunu söyleyebiliriz. Şimdiki adımımız bu veri kümesi üzerinden SVM algoritmasını çalıştırmak olacak<strong>.</strong></p>
<p><strong>3. Adımda</strong> WEKA&#8217;nın ilk açılan ana ekranına dönerek, bu sefer &#8220;Explorer&#8221; düğmesine basıyoruz ve WEKA içerisinde yer alan fonksiyonları kullanacağımız ekran açılıyor.</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM4.png" alt="" /></p>
<p>Yukarıdaki açılan Weka Explorer ekranında bulunan ilk sekme olan Preprocess sekmesinde (ki ilk açıldığında bu sekme açık gelir), bulunan &#8220;Open File&#8221; düğmesine tıklayarak dosya seçicimizi açıyoruz ve yine Weka&#8217;nın kurulumuyla gelen data dizini altında bulunan &#8220;labor.arff&#8221; dosyasını seçerek açıyoruz.</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM5.png" alt="" /></p>
<p>Ekranda, seçilen bu dosyanın ön işleme sonuçları görülüyor. Buna göre sol taraftaki listede, ilk başta görüntülediğimiz arff dosyasının her bir kolonu yer almakta olup, her kolona tıklandığında, bu kolon ile ilgili veri detayları sağ tarafta çubuk grafik olarak görülmektedir.</p>
<p><strong>4. Adımda</strong> WEKA&#8217;nın sınıflandırma işlemi için ilgili modülün yüklenmesine geçecegiz. Bu işlem için, ekranın üzerinde bulunan &#8220;Classify&#8221; sekmesine geçiyoruz.</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM6.png" alt="" /></p>
<p>Sekmeye geçtikten sonra &#8220;Choose&#8221; düğmesine tıklayarak kullanacağımız modülü seçeceğiz. Burada WEKA içerisinde yüklü olan ve konu ile ilgisi olan 3 ayrı modülden bahsetmekte yarar vardır:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM7.png" alt="" /></p>
<p>Listede görülen classifiers klasörü altındaki functions elemanlarıdır. Bunların tamamı, sınıflandırma için kullanılan fonksiyonlardır. Tam bu noktada 3 ayrı alternatiften bahsedelim:</p>
<p><strong>SMO<br />
</strong></p>
<p>Yani birden fazla kümeye, veriyi bölmeye yarar. Listede bulunan SMO, SVM benzeri bir yapıdadır.</p>
<p>Sequential Minimal Optimisation kelimelerinin baş harflerinden oluşan SMO, esas itibariyle Suppor Vector kullanan bir algoritmadır. Algoritmanın detayı için WEKA dokümantasyonunda da yer alan aşağıdaki makalelere bakılabilir:</p>
<ul>
<li>J. Platt: Fast Training of Support Vector Machines using Sequential Minimal Optimization. In B. Schoelkopf and C. Burges and A. Smola, editors, Advances in Kernel Methods &#8211; Support Vector Learning, 1998.</li>
<li>S.S. Keerthi, S.K. Shevade, C. Bhattacharyya, K.R.K. Murthy (2001). Improvements to Platt&#8217;s SMO Algorithm for SVM Classifier Design. Neural Computation. 13(3):637-649.</li>
<li>Trevor Hastie, Robert Tibshirani: Classification by Pairwise Coupling. In: Advances in Neural Information Processing Systems, 1998.</li>
</ul>
<p><strong>LibSVM<br />
</strong></p>
<p>SVM sınıflandırıcısının en önemli kütüphanesi, bir doktora tezi sırasında ortaya çıkmış olan ve libSVM olarak bilinen açık kaynak kodlu kütüphanedir. Bu kütüphane, ne yazık ki WEKA kurulumu ile gelememektedir. Ancak bu kütüphaneyi WEKA altında kullanmanın iki yolu bulunur. İlki, kütüphaneyi WEKA&#8217;ya tanıtmaktır. Bunun için, yukarıdaki temsili resmi verilen listede bulunan libSVM kullanılabilir. Öncelikle kütüphane, aşağıdaki adresten indirlmelidir:</p>
<p><a href="http://www.csie.ntu.edu.tw/~cjlin/libsvm/">http://www.csie.ntu.edu.tw/~cjlin/libsvm/</a></p>
<p>Ardından weka&#8217;nın paket yöneticisi tarafından kurulmalıdır. Wekanın paket yöneticisi ise WEKA&#8217;nın classpath tanımının yapıldığı bir konsolda aşağıdaki komutu vererek çalıştırılabilir:</p>
<p><span style="font-family: Courier New; font-size: 10pt;">java weka.core.WekaPackageManager<br />
</span></p>
<p>&nbsp;</p>
<p>Diğer bir yöntem ise, indirilen libsvm kütüphanesinin WEKA classpath&#8217;ine eklenmesidir. İlgili ayarlar yapıldıktan sonra 4. adımda bahsettiğimiz sınıflandırmalardan birisi olarak libSVM kullanılabilir.</p>
<p>LibSVM kullanımı için ikinci bir yöntem ise, LibSVM ve WEKA programlarını, aynı anda içeren wlsvm kütüphanesini kullanmaktır. Bu kütüphaneye de aşağıdaki adresten erişilebilir:</p>
<p><a href="http://www.cs.iastate.edu/~yasser/wlsvm/">http://www.cs.iastate.edu/~yasser/wlsvm/</a></p>
<p><strong>SMOreg<br />
</strong></p>
<p>SVM ile ilgili, weka içerisinde bulunan 3. bir seçenek de SMOreg seçeneğidir. Bu seçenek, SVM üzerinde Regression (ilkelleme, regrezizasyon) uygulamaya yarayan kütüphanedir. Bu kütüphane için de detaylı bilgi, aşağıdaki kaynaklardan edinilebilir:</p>
<ul>
<li><span style="font-family: Times New Roman; font-size: 12pt;">Alex J. Smola, Bernhard Scholkopf (1998). <em>A Tutorial on Support Vector Regression</em>. NeuroCOLT2 Technical Report Series &#8211; NC2-TR-1998-030.<br />
</span></li>
<li><span style="font-family: Times New Roman; font-size: 12pt;">S.K. Shevade, S.S. Keerthi, C. Bhattacharyya, K.R.K. Murthy, <em>Improvements to SMO Algorithm for SVM Regression</em>. Technical Report CD-99-16, Control Division Dept of Mechanical and Production Engineering, National University of Singapore.<br />
</span></li>
</ul>
<p><strong>5. Adımda</strong>, Yukarıdaki seçeneklerden birisi seçildikten sonra, seçilen modüle göre ayarlama yapılması gerekemektedir. Örneğin SMO kütüphanesi üzerinden ilerleyecek olalalım. Bu modülün parametre ayarlarını, Object Editor ile yapabiliriz. ObjectEditor&#8217;ü açmak için ekranda bulunan ve fonksiyonun parametrelerini içeren metin kutusuna tıklamak yeterlidir:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM8.png" alt="" /></p>
<p>Açılan bu ekranda, ilgili parametre ayarları yapıldıktan sonra, sınıflandırma fonksiyonunun çalışması için, WEKA Explorer ekranında bulunan &#8220;Start&#8221; düğmesine basmak yeterli olacaktır. Sonuçlar ve sonuçların değerlendirmeleri (hata miktarları gibi), sonuç ekranında görülecektir. Buradaki sonucu etkileyen diğer bir ayar da, kullanım sırasında eğitim ve test için izlenecek stratejidir.</p>
<p>WEKA doğrudan, 4 farklı özellik desteklemektedir. Bunlar sırasıyla aşağıda anlatılmıştır:</p>
<p><img src="http://www.bilgisayarkavramlari.com/wp-content/uploads/091911_0537_WEKAileSVM9.png" alt="" /></p>
<p>Trainin set seçeneği, seçilen verinin sadece eğitim amaçlı kullanılmasını sağlar. Bu seçenekte önce eğitim yapılıp ardından ikinci bir küme, test amaçlı kullanılabilir. Bu seçenek de yine yukarıdaki ekranda bulunan &#8220;Supplied test set&#8221; seçeneği ile gösterilen küme üzerinde çalışır.</p>
<p>&#8220;Cross-validation&#8221; seçeneği, veri kümesine belirtilen (folds sayısı olarak belirtilen) sayıda kümeye böler. Alt kümelerden birisini eğitim kümesi olarak kabul ederek sistemi eğitir. Ardından bu eğitim sonucunu diğer bir alt küme üzerinde sınar (ki bu kümeye sınama kümesi (validating set) veya test kümesi (test set) ismi verilir). Bu işlemi belirtilen küme sayısı kadar tekrarlayarak sisemi iyileştirmeye çalışır.</p>
<p>Son seçenek olan &#8220;percentage split&#8221; ise, verilen oranda kümeyi ikiye böler ve ilk kümeyi eğitim ikinci kümeyi ise test amaçlı kullanır. Örneğin %66 bölümün anlamı, kümenin ilk %66 kısmının eğitim sonraki %34 kısmının ise test amaçlı kullanılacağıdır.</p>

<p class="sayac_bilgi">605 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/09/19/weka-ile-svm/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Apriori Algoritması</title>
		<link>http://www.bilgisayarkavramlari.com/2011/09/07/apriori-algoritmasi/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/09/07/apriori-algoritmasi/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 09:33:44 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/2011/09/07/apriori-algoritmasi/</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Veri madenciliğinde kullanılan ve veri kümeleri veya veriler arasındaki ilişkiyi çıkarmak için geliştirilmiş algoritmanın ismidir. Ayrıca pek çok akademik konuda geçen ve temelini felsefeden (ve daha özel olarak mantıktan) alan a priori konusu için bu bağlantıyı tıklayabilirsiniz. Apriori algoritması, özellikle çok büyük ölçekli veri tabanları (VLDB, very large databases) üzerindeki [...]]]></description>
			<content:encoded><![CDATA[<p>Yazan : Şadi Evren ŞEKER</p>
<p>Veri madenciliğinde kullanılan ve veri kümeleri veya veriler arasındaki ilişkiyi çıkarmak için geliştirilmiş algoritmanın ismidir. Ayrıca pek çok akademik konuda geçen ve temelini felsefeden (ve daha özel olarak mantıktan) alan a <a href="http://www.bilgisayarkavramlari.com/2011/08/13/apriori-malum-aposteriori-afortiori/">priori konusu için bu bağlantıyı tıklayabilirsiniz</a>.</p>
<p>Apriori algoritması, özellikle çok büyük ölçekli veri tabanları (VLDB, very large databases) üzerindeki veri madenciliği (datamining) çalışmalarında geliştirilmiştir. Genel anlamda münasebet kuralı (association rule, birliktelik kuralı) çıkarımında kullanılan bir algoritmadır. Algoritmanın amacı, veri tabanında bulunan satırlar arasındaki bağlantıyı ortaya çıkarmaktır.</p>
<p>Algoritmanın ismi, kendinden önceki çıkarımlara bağlı olduğu için, latince, önce anlamına gelen &#8220;prior&#8221; kelimesinden gelmektedir.</p>
<p>Algoritma yapı olarak, aşağıdan yukarıya (bottom-up) yaklaşımı kullanmakta olup, her seferinde tek bir elemanı incelemekte ve bu elemanla diğer adaylarla münasebetini ortaya çıkarmaya çalışmaktadır.</p>
<p>Ayrıca algoritmanın her eleman için çalışmasını, bir arama algoritmasına benzetmek mümkündür. Algoritma, bu anlamda <a href="http://www.bilgisayarkavramlari.com/2008/11/13/sig-oncelikli-arama-breadth-first-search/">sığ öncelikli arama (breadth first search)</a> yapısında olup, sanki adayları birer <a href="http://bilgisayarkavramlari.com/2008/05/07/agaclar-tree/">ağaç (tree)</a> gibi düşünerek bu ağaç üzerinde arıyor kabul edilebilir.</p>
<p>Ağaç yapısında, k elemanlı bir aday listesinden k-1 elemana baktıktan sonra, alt frekans örüntüsü yetersiz olan elemanları budamakta ve kalan elemanların üzerinden arama yapmaya devam etmektedir.</p>
<p><strong>Örnek<br />
</strong></p>
<p>Algoritmayı daha iyi anlamak için bir örnek üzeridnen inceleyelim.</p>
<p>Bir firmanın ürünlerink SKU numaraları ile (Stock Keeping Unit, depo numarası), veritabanında tuttuğunu düşünelim. Bu durumda firmanın satılan ürünlerden hangilerinin beraber alındığını bulma şansı olabilir. Örneğin kasada işlem yapıldığında aynı fatura içerisinde yer alan SKU&#8217;ların beraber satıldığını kabul edelim.</p>
<p>Örneğin faturaların tutulduğu veri tabanı tablosundaki kayıtlar aşağıdaki şekilde olabilir:</p>
<p>{1,2,3,4},</p>
<p>{1,2},</p>
<p>{2,3,4},</p>
<p>{2,3},</p>
<p>{1,2,4},</p>
<p>{3,4},</p>
<p>{2,4}</p>
<p>Yukarıdaki her faturada, hangi ürünün diğer hangi ürünlerle birlikte satıldığı görülmektedir. Buna göre, örneğin yukarıdaki listedeki ikinci satır, firmanın sattığı ürünlerden 1 ve 2 SKU numarasına sahip ürünleri temsil etmektedir (diyelim ki 1 numaralı ürün kravat ve 2 numaralı ürün gömlek olsun, bu durumda ikinci satır, {1,2} kayıdı ile bize gömlek ve kravatın beraber satıldığını anlatmaktadır)</p>
<p>Apriori algoritmamızın ilk adımı, her ürünün frekansını, yani kaç kere listede geçtiğini saymak olacaktır.</p>
<div>
<table style="border-collapse: collapse;" border="0">
<colgroup>
<col style="width: 37px;" />
<col style="width: 53px;" /></colgroup>
<tbody valign="top">
<tr>
<td style="border: outset 0.75pt; padding: 1px;" valign="middle">Ürün</td>
<td style="border-top: outset 0.75pt; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">Frekans</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">1</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">3</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">2</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">6</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">3</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">4</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">4</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">5</td>
</tr>
</tbody>
</table>
</div>
<p>Yukarıdaki tabloda, her ürünün toplam satış sayısı bulunmaktadır. Bu değere frekans veya destek (support) ismi verilmektedir.</p>
<p>Algoritmanın ikinci adımında, asgari destek değerini belirliyoruz. Bu belirleme işlemi, üretilen tabloya göre değişebilmektedir. Yukarıdaki örnek için asgari desteğimiz 3 olsun.</p>
<p>Algoritmanın sıradaki adımı, ürünleri 2&#8242;li gruplara ayırmak olacak. Buradaki amaç her elemanın diğer elemanlarla olan münasebetini bulmak. Yukarıdaki tabloda, frekansı düşük olan (daha seyrek olan, sık geçmeyen) elemanları eliyoruz. Bunların sonuç listesinde de yer almayacağını kabul ediyoruz.</p>
<p>Bu defa tablomuzda sadece 2 elamanlı listeleri bulunduruyoruz:</p>
<div>
<table style="border-collapse: collapse;" border="0">
<colgroup>
<col style="width: 37px;" />
<col style="width: 57px;" /></colgroup>
<tbody valign="top">
<tr>
<td style="border: outset 0.75pt; padding: 1px;" valign="middle">Ürün</td>
<td style="border-top: outset 0.75pt; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">Frekans(Destek)</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">{1,2}</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">3</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">{2,3}</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">3</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">{2,4}</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">4</td>
</tr>
<tr>
<td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">{3,4}</td>
<td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt; padding: 1px;" valign="middle">3</td>
</tr>
</tbody>
</table>
</div>
<p>Yukarıdaki tabloda bulunan değerleri listelerdeki çiftlerden çıkmıştır. Örneğin {1,2} değeri, 3 yerde geçmektedir ve bunlar:</p>
<p>{1,2,3,4},</p>
<p>{1,2},</p>
<p>{1,2,4},</p>
<p>Listeleridir ( veya senaryomuz gereği faturalar olarak düşünülebilir). Dolayısıyla {1,2} ikilisi için 3 frekansı hesaplanmış olur.</p>
<p>Yukarıdaki listenin devamında 3 elemanlı listelerin tablosu da çıkarılabilir ancak ne yazık ki 3 veya 4 elamanlı liste örneğimizde çıkarılamamaktadır. Bunun sebebi asgari destek değerimizi 3 kabul etmiş olmamızdır. Örneğin {1,2,4} şeklindeki faturayı ele alalım. Bu değer sadece 2 yerde geçmektedir:</p>
<p>{1,2,3,4},</p>
<p>{1,2,4},</p>
<p>Ve dolayısıyla frekans değeri (destek değeri) 2 olmaktadır. Bu destek değeri, asgari destekten küçük olduğu için kabul edilmemektedir.</p>
<p><strong>Algoritma<br />
</strong></p>
<p>Konu üzerindeki ilk yayını yapan Agrawal ve Srikat, tarafınan algoritmanın müsvette kodu (pseudo code) aşağıdaki şekilde verilmiştir.</p>
<p>L<sub>1 </sub>= {sık tekrarlanan öğeleri içeren küme}</p>
<p>for(k=2; L <sub>k-1</sub> != 0 ; k++){</p>
<p>C<sub>k</sub> = apriori-üret (L <sub>k-1</sub>);</p>
<p>forall (işlemler t <span style="font-family: Symbol;">Î</span>D){</p>
<p>C<sub>t</sub><span> </span> ⊂ (C<sub>k</sub>,t);</p>
<p>forall adaylar c <span style="font-family: Symbol;">∈</span> C<sub>t</sub>{</p>
<p>c.sayaç++;</p>
<p>}</p>
<p>}</p>
<p>L<sub>k</sub>={ c ∈C<sub>k</sub> | c.sayaç = enküçük }</p>
<p>}</p>
<p>Sonuç = U<sub>k</sub> L<sub>k</sub>;</p>
<p>Algoritmayı açıklayacak olursak, algoritmadaki L, veri tabanı veya veri kümemizde bulunan öğeleri temsil etmektedir. Apriori üret fonksiyonundan üretilen her bir C<sub>k</sub> kümesi için, t bir işlem (transaction) olmak üzere, üretilen bu Ck kümesinin t işlemini tutan sayacı, her münasebette bir arttırıyoruz. Ardından sıradaki L değerini alarak algoritmamız çalışmaya devam ediyor. Sonuç olarak da üretilen bu L değerlerinin birleşim kümesini döndürüyoruz.</p>
<p>Yukarıdaki algoritmada belirsiz olan apriori-üret fonksiyonunu ise aşağıdaki şekilde verebiliriz:</p>
<p>C<sub>k</sub>&#8216;ya ekle</p>
<p>select p.eleman<sub>1</sub>, p.eleman<sub>2</sub>, &#8230; p.eleman <sub>k-1</sub>, q.eleman <sub>k-1</sub></p>
<p>for(L <sub>k-1</sub> p&#8217;den L <sub>k-1</sub> q&#8217;ya kadar)</p>
<p>where p.eleman<sub>1</sub>, p.eleman<sub>2</sub>, &#8230; p.eleman <sub>k-2</sub> = q.eleman <sub>k-2 , </sub>p.eleman <sub>k-1</sub> &lt; q.eleman <sub>k-1</sub></p>
<p>forall elemanlar c ∈C<sub>k</sub> {</p>
<p>forall c&#8217;nin (k-1)-alt kümesi s için{</p>
<p>if( s ∉L <sub>k-1</sub> ){</p>
<p>c&#8217;yi C<sub>k</sub> &#8216;dan sil</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>Yukarıdaki algoritma, basitçe bütün adayların üretilerek elemanların aday kümelerine konulmasını hedeflemektedir.</p>
<p>&nbsp;</p>

<p class="sayac_bilgi">302 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/09/07/apriori-algoritmasi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hırsız Oyunu (Game of Nim)</title>
		<link>http://www.bilgisayarkavramlari.com/2011/06/23/hirsiz-oyunu-game-of-nim/</link>
		<comments>http://www.bilgisayarkavramlari.com/2011/06/23/hirsiz-oyunu-game-of-nim/#comments</comments>
		<pubDate>Thu, 23 Jun 2011 03:57:34 +0000</pubDate>
		<dc:creator>Şadi Evren ŞEKER</dc:creator>
				<category><![CDATA[yapay zeka (artificial intelligence)]]></category>

		<guid isPermaLink="false">http://www.bilgisayarkavramlari.com/2011/06/23/hirsiz-oyunu-game-of-nim/</guid>
		<description><![CDATA[Yazan : Şadi Evren ŞEKER Bu yazının amacı, hırsız oyunu (game of nim) isimli oyun &#252;zerinden asgari-azami ağa&#231;ları (minimax trees) a&#231;ıklamaktır. &#214;ncelikle oyunu kısaca anlatalım. Oyun iki kişi tarafından karşılıklı olarak sırayla oynanmaktadır. Oyun sayılabilir varlıklar &#252;zerinden oynanır. &#214;rneğin boncuk, &#231;ubuk, kalem gibi sayılabilir varlıklar oyun i&#231;in kullanışlıdır. Bu yazı boyunca &#231;ubuk kullanıldığını d&#252;ş&#252;nerek konuyu [...]]]></description>
			<content:encoded><![CDATA[<div>
<p style="margin-bottom: 0cm">Yazan : Şadi Evren ŞEKER</p>
<p style="margin-bottom: 0cm">Bu yazının amacı, hırsız oyunu (game of nim) isimli oyun &uuml;zerinden  <a href="http://www.bilgisayarkavramlari.com/2009/04/29/minimax-agaclari-minimax-tree/">asgari-azami ağa&ccedil;ları (minimax trees)</a> a&ccedil;ıklamaktır. &Ouml;ncelikle oyunu kısaca anlatalım.</p>
<p style="margin-bottom: 0cm">Oyun iki kişi tarafından karşılıklı olarak sırayla oynanmaktadır. Oyun sayılabilir varlıklar &uuml;zerinden oynanır. &Ouml;rneğin boncuk, &ccedil;ubuk, kalem gibi sayılabilir varlıklar oyun i&ccedil;in kullanışlıdır. Bu yazı boyunca &ccedil;ubuk kullanıldığını d&uuml;ş&uuml;nerek konuyu izah edelim.</p>
<p style="margin-bottom: 0cm">Başlangı&ccedil;ta n miktarda &ccedil;ubuk ile oyuna başlanır. Bu n sayısı imkanlar dahilinde değişmekle birlikte m&uuml;mk&uuml;nse asal sayı almak daha iyidir ki taraflardan birisi hızlı bir hesaplama ile hile yapamasın <img src='http://www.bilgisayarkavramlari.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="margin-bottom: 0cm">Bu &ouml;rnekte 7 olarak kabul edelim.</p>
<p style="margin-bottom: 0cm">Oyuna 7 adet &ccedil;ubuk ile başlıyoruz. Sıra kendisinde olan taraf &ccedil;ubukları iki gruba ayırıyor. Grupların b&uuml;y&uuml;kl&uuml;ğ&uuml;ne kendisi karar veriyor. &Ouml;rneğin 7 &ccedil;ubuğu, 1+6, 2+5, 3+4 şeklinde gruplara ayırabilir.</p>
<p style="margin-bottom: 0cm">Ardından sıra diğer oyuncuya ge&ccedil;iyor ve bu oyuncu da gruplardan istediğini iki gruba b&ouml;l&uuml;yor ve oyun b&ouml;ylelikle s&uuml;r&uuml;p gidiyor. En sonunda taraflardan birisi artık iki gruba ayıramayacak hale gelince oyunu diğer taraf kazanmış oluyor. Oyunda gruplara ayırma sırasında bir de istisna bulunuyor. Buna g&ouml;re eşit sayıda iki gruba b&ouml;lemiyoruz. &Ouml;rneğin 6 &ccedil;ubuk olması halinde 3+3 şeklinde iki gruba b&ouml;lmek yasak. Dolayısıyla 2 &ccedil;ubuk kalması halinde oyun bitiyor &ccedil;&uuml;nk&uuml; oyuncu 1+1 şeklinde b&ouml;lemez.</p>
<p style="margin-bottom: 0cm">Oyunun &ouml;rnek hamle ağacını aşağıdaki şekilde &ccedil;izebiliriz:</p>
<p style="margin-bottom: 0cm"> <img border="0" height="210" name="grafik1" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/sbres_1308801595_0__.jpg" style=";text-align:left" width="319">  </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm">Yukarıdaki ağa&ccedil;ta g&ouml;r&uuml;ld&uuml;ğ&uuml; &uuml;zere, oyun 7 adet &ccedil;ubuk ile başlamış ve b&uuml;t&uuml;n ihtimaller ağa&ccedil;ta g&ouml;sterilmiştir. Ağa&ccedil;ta g&ouml;r&uuml;ld&uuml;ğ&uuml; &uuml;zere oyunun 3 farklı bitiş koşulu bulunmaktadır. Bu bitişler aşağıdaki şekilde işaretlenmiştir:</p>
<p style="margin-bottom: 0cm"> <img border="0" height="210" name="grafik2" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/sbres_1308801595_1__.jpg" style=";text-align:left" width="319">  </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm">Bitişler, aynı zamanda kazananı da belirlemektedir. Yukarıdaki bu ağa&ccedil; &uuml;zerinde asgari-azami ağacı işaretleyecek olursak, aşağıdaki şekli elde ederiz:</p>
<p style="margin-bottom: 0cm"> <img border="0" height="231" name="grafik3" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/sbres_1308801595_2__.jpg" style=";text-align:left" width="400">  </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm">Yukarıdaki şekilde, ağa&ccedil;ta g&ouml;sterilen değerler, hamlelere karar verme sırasında kullanılmaktadır. &Ouml;rneğin yukarıdaki şekle bakıldığında her durumda 1 sonucuna ulaşılabilecek hamleler yapılacağı g&ouml;r&uuml;lmektedir. Diğer bir deyişle 1 sonucu, bizim kazanma durumumuzu g&ouml;stermekte ve %100 ihtimal ile oyunu kazanmaktayız.</p>
<p style="margin-bottom: 0cm">İlk hamleyi Rakip oyuncu yapıyor ve ilk hamlede b&uuml;t&uuml;n ihtimaller &uuml;zerinde 1 değeri olduğu i&ccedil;in ne oynadığının hi&ccedil; &ouml;nemi yok. Diyelim ki 5+2 ihtimalini oynadı. Bu durumda mecburen 5 grubunu b&ouml;leceğiz (2 grubunu b&ouml;lemez &ccedil;&uuml;nk&uuml; b&ouml;lmesi halinde iki eşit grup oluşacaktır). 5 grubunu ise iki farklı şekilde b&ouml;l&uuml;nebilir: 4+1 veya 3+2.</p>
<p style="margin-bottom: 0cm">Bu hamlelerden bizim i&ccedil;in karlı olanı, 4+2 şeklinde b&ouml;lmek &ccedil;&uuml;nk&uuml; bu hamle bize oyunu kazandıracak (3+2+2 kolunda 0 değeri olduğuna dikkat ediniz)</p>
<p style="margin-bottom: 0cm">Sıra tekrar rakibe ge&ccedil;ince yapabileceği tek hamle 4+2+2 grubundaki 4 değerini 3+1 şeklinde b&ouml;lmek olacaktır.</p>
<p style="margin-bottom: 0cm">Biz ise son hamleyi yapıp 3 grubunu 2+1 olarak b&ouml;l&uuml;yor ve oyunu kazanıyoruz.</p>
<p style="margin-bottom: 0cm">Yukarıda g&ouml;r&uuml;ld&uuml;ğ&uuml; &uuml;zere oyunun b&uuml;t&uuml;n hamlelerini minimax ağacı &uuml;zerinde hesaplayarak bir sonuca eriştik ve oyunu kesin olarak kazanacağımızı biliyoruz. Ayrıca yukarıdaki ağa&ccedil;ta  <a href="http://www.bilgisayarkavramlari.com/2007/12/03/dinamik-programlama-dynamic-programming/">dinamik programlama (dynamic programming)</a> kullanılmıştır. Yani, &ouml;rneğin 4+2+1 sonucuna iki farklı yerden ulaşılabilmektedir. (6+1 veya 5+2&#8242;den) Ağa&ccedil;ta bu değerler ayrı ayrı g&ouml;sterilmek yerine tek bir d&uuml;ğ&uuml;mde g&ouml;sterilmiştir. Bu sayede ağacın karmaşıklığı indirgenmiştir.</p>
<p style="margin-bottom: 0cm">Yukarıdaki oyunun minimax ağacını daha da verimli hale getirebiliriz. Bunun i&ccedil;in  <a href="http://www.bilgisayarkavramlari.com/2009/11/23/alfa-beta-budamasi-alpha-beta-prunning/">alfa beta budaması (alfa beta prunning)</a> kullanmayı deneyelim. Konu hakkında bilgisi olmayanlar ilgili yazıyı, linke tıklayarak okuyabilirler.</p>
<p style="margin-bottom: 0cm"> <img border="0" height="229" name="grafik4" src="http://www.bilgisayarkavramlari.com/wp-content/uploads/sbres_1308801595_3__.jpg" style=";text-align:left" width="395">  </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm"> </p>
<p style="margin-bottom: 0cm">Yukarıdaki ağa&ccedil;ta, iki dal budanmıştır. Bunun sebebi, ağacın dolaşılması sırasında, azami değerin alınacağı seviyede 1 değerine ulaşılmış olması ve sonrasında gelen değerlerin bir &ouml;nemi olmamasıdır. &Ouml;rneğin 5+2 d&uuml;ğ&uuml;m&uuml;ne, 1 değeri 4+2+1 d&uuml;ğ&uuml;m&uuml;nden taşındıktan sonra diğer koldan ne geldiğinin artık bir &ouml;nemi yoktur &ccedil;&uuml;nk&uuml; azami değere ulaşılmıştır. Bu sayede bazı kolların altındaki değerlerin hesaplanmasına gerek kalmadan sonuca daha hızlı bir şekilde ulaşılmış olunur.</p>
<p><br clear="left"></div>

<p class="sayac_bilgi">615 views</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bilgisayarkavramlari.com/2011/06/23/hirsiz-oyunu-game-of-nim/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

