Merhaba arkadaslar ilk defa e-bergi'de bana yazma şansı veren arkadaşlarıma teşekkür ederek yazıma başlamak istiyorum. Bu ay sizlere Rule Engines (Kural Motorları) hakkında kısa bilgiler vererek, bilgilendirmeye çalışacağım.

Kural motorları, belli iş kurallarını uygulayan yazılım sistemleridir. Örneğin bir defada 100 ytl den fazla alışveriş yapan müşterilere 10 ytl lik hediye çeki verilir. Bu örnek kuralları kafamızda daha net canlandırabilmemize yardımcı olacaktır. Anlayabileceğiniz gibi bu çok basit bir örnektir, bu örnekleri iş hayatındaki bir çok sektör için genişletebilirsiniz. Bir diğer nokta da, eğer dikkat ettiyseniz kuralların basit 'if – then' kalıpları olarak kurulmasıdır.

Kuşkusuz en önemli soruların başında kural motorlarının neden bu kadar önemli ve kullanışlı olduğu gelicektir. Herhangi bir bilgi teknolojisinde iş kuralları, uygulamanın kendisine göre çok daha sık aralıklarla değişir. Bu noktada kural motorlarının daha ayrıntılı tanımını yapabiliriz. Kural motorları, uygulama kodundan harici olarak oluşturulan iş kurallarını çalıştıran tak-çıkar yazılım parçalarıdır. Böylece ana uygulama kodunu değiştirmeden değişen iş kurallarına göre yazılımımızı kolaylıkla değiştirebiliriz. Kısaca kural motorlarının faydalarını şöyle özetleyebiliriz:

  • Kuralların anlaşılması genelikle kolaydır.
  • Kurallar geleneksel programlama dillerinden daha fazla rahatlık ve özgürlük sağlarlar.
  • Kuralar bilgiyi uygulama mantığından ayırırlar.
  • Kurallar ana uygulama kodunu değiştirmeden değiştirilebilirler, bu yüzden uygulama kodunu tekrar derlemeye gerek kalmaz.

İş kuralları seti, bir organizyona uygulanan, organizyonun amacına ulaşabilmesi için gerekli tanımlamaları, operasyonları, kısıtlamaları içerir. Aslında yapay zeka çalışmaları iş kuralları konusuna oldukça girmektedir. Eldeki bir veri yapısına, yeni bir kuralın koşulunun eldeki gerçeklerden birine uyması sonucu o kuralın sonuç kısmı (then kısmı) uygulanır. Burada ufak bir örnek verebiliriz. Kurallarımız:

P1: $$ -> *
P2: *$ -> *
P3: *x -> x*
P4: * -> null & halt
P5: $xy -> y$x
P6: null -> $

olsun. $ ve *' ın işaret sembolleri olarak kullanıldığını düşünebiliriz. Bu kuralları uygulayarak 'ABC' yi tersine çevireceğiz. Adımları sırasıyla takip edebilirsiniz,

$ABC (P6)
B$AC (P5)
BC$A (P5)
$BC$A (P6)
C$B$A (P5)
$C$B$A (P6)
$$C$B$A (P6)
*C$B$A (P1)
C*$B$A (P3)
C*B$A (P2)
CB*$A (P3)
CB*A (P2)
CBA* (P3)
CBA (P4)

Bu çok basit örnek kural motorlarının işlevi hakkında daha net bir fikir vermiştir umarım. Tabi ki bir gerçek iki farklı kuralın koşulunu aynı anda sağlayabilir, bu tür durumlar için ayrı mekanizmalar geliştirilmiştir.

Kural Motorları Çeşitleri

Kural motorlarını kısaca ikiye ayırabiliriz: üretici kural motorları (production rule engines) ve tepkisel kural motorları (reactive rule engines). Her iki kural motoru da 'forward chaining' (ileriye dönük zincirleme) methodunu kullanır. Forward chaining, yapay zeka çalışmalarında kullanılan iki düşünme methodundan biridir, bir diğeri de 'backward chaining' (geriye dönük zincirleme)dir. Kural motorlarının çesitlerine geçmeden önce bu iki metodu inceleyelim biraz. İsimlerinden anlaşıldığı gibi bu methodlar birbirinin zıttı olarak çalışır. Bu iki metodun basit bir örnek üzerinde nasıl çalıştıklarını anlamak, bu metodları ayırt etmemizde bize çok yardımcı olacaktır. Örneğin 'vakvak' isimli hayvanın rengini bulmak istiyoruz. Elimizde onun vakvakladığı ve gagasının olduğu gerçekleri var. Elimizde de dört tane kural olsun:

  1. Eğer A vakvaklıyorsa ve gagası varsa ördektir.
  2. Eğer A vıraklıyorsa ve suda yaşiyorsa kurbağadır.
  3. Eğer A ördekse beyazdır.
  4. Eğer A kurbağaysa yeşildir.

Forward chaining metodunda, kurallar seti araştırılır ve ilk kural seçilir. Çünkü elimizdeki gerçekler ilk kuralın koşuluyla uyuşuyor. İlk kuralın sonucunu gerçeklerimizin arasına ekliyoruz. Tekrar bir araştırma yaptığımızda bu sefer üçüncü kuralın koşuluyla elimizdeki gerçeklerin uyuştuğunu görüyoruz. Yani 'vakvak' isimli hayvanın renginin beyaz olduğunu gerçeklerimiz arasına katıyoruz. Gördüğünüz gibi amacımıza ulaşmış olduk.

Backward chainingde de aynı kurallar seti olduğunu ve aynı amacı taşıdığımız varsayalım. Araştırma yaptığımızda üçüncü ve dördüncü kuralları seçeriz, çünkü onların sonucu bizim amacımızla uyuşuyor. Hala 'vakvak' ın ördek mi kurbağa mı olduğunu bilmiyoruz. Bu yüzden bu iki koşulu da amaç listemize ekliyoruz. Tekrar kurallar setinde araştırma yaptığımızda bu sefer ilk iki kuralı seçiyoruz, çünkü sonuçları bizim amaç listemizle uyuşuyor. Bunlardan ilk kuralın koşulunun bizim elimizdeki gerçekle uyuştuğunu anladığımızda 'vakvak'ın ördek olduğunu anlıyoruz. Çoğumuzun az çok bildiği prolog dili de backward chainingi destekleyen programlama dillerinden biridir. Forward chainingin bir avantajı değişen gerçeklere daha kolay ayak uyduran dinamik bir yapısının olmasıdır.

Şimdi gelelim asıl konumuza, yani üretici ve tepkisel kural motorlarına. Dediğim gibi her ikisi de forward chaining kullanıyor. Üretici kural motorları basit 'if-then' kalıplarını uygularlar. Eğer bir kuralın koşulu sağlanıyorsa o kural çalıştırılır. Tepkisel kural motorları, gelişecek olan olayları tespit eder ve bunlara göre tepki gösterirler. Örneğin müdürü stokların biteceğine dair uyarmak tepkisel bir kural motorunun çalışması sonucu gerçekleşebilir. Aralarındaki en büyük fark ise, üretici kural motorlarının kuralların koşulu sağlandığında genelde stateless durumlarda çağrılması, tepkisel kural motorlarının olayların oluşması durumunda otomatik olarak çağrılması yani genelde stateful durumlarda çağrılmasıdır. Günümüz kural motorları, her iki çeşitten de özellikler taşımaktadırlar.

Rete Algoritması

Kural motorları denince akla gelen bir diğer konu da Rete Algoritmasıdır. Bu algoritmaya da kısa bir şekilde değinmek istiyorum. Bu algoritma Dr Charles L. Forgy tarafından geliştirilmiştir. Gerçekte kurallar setinin binlerce hatta onbinlerce kurallardan oluşabileceği aşikar. Bu yüzden kurallar dizisini araştırırken çoğu kuralın koşulunun gerçeklerimize uymadığını ve çoğunu gereksiz yere araştırdığımızı biliyoruz aslında. Ancak çoğu kural bir önceki araştırmamızdakiyle aynı sonucu veriyor. Böyle olunca değişen gerçeklerle tüm kurallar listesini baştan sona tekrar araştırmak çok verimsiz bir yol oluyor. Bu yolun karmaşıklığını O(RFP ) olarak ifade edersek verimsizliğininin miktarını daha iyi anlayabiliriz sanırım. (R -> Kurallar sayısı, P-> Her kuraldaki ortalama koşul sayısı, F-> Gerçeklerin sayısı)

Rete Algortiması kullanılarak, bu kurallar setini araştırma işinin verimliliği arttırılıp, karmaşıklığı _O(RFP)_ye düşürülebiliyor. Rete Algortiması ile eski araştırmaların sonucu hatırlanıp, ona uygun olarak yeni eklenen gerçekler, ilişkili olduğu kurallarla karşılaştırılır. Bunu yaparken de ağaç yapısına benzer bir yapı kullanılır. Bu algoritma hakkında daha ayrıntılı bilgiye aşağıda belirttiğim kaynaklardan ulaşabilirsiniz.

Son olarak günümüzdeki popüler kural motorlarının adlarını veriyim: C# kaynaklı kural motorlarına NxBRE, Drools.NET ve SRE'yi verebiliriz. Java kaynaklı kural motorlarına Drools, Fair Isaac Blaze Advisor, ILOG JRules, and Jess verilebilir. Java kaynaklı kural motorları JSR 94 standardını kullanarak kendi aralarında geçiş yapabilirler. Populer kural motorlarından biri olan Jess in kullanımıyla ilgili küçük bir örnek görmek hoş olabilir.

Jess> (defrule library-rule-1
    (book (name ?X) (status late) (borrower ?Y))
    (borrower (name ?Y) (address ?Z))
   =>
    (send-late-notice ?X ?Y ?Z))

Bu kural şöyle çevrilebilir:

Kütüphane Kuralı-1
Eğer
X isimli Y adlı bir kişi tarafından ödünç alınmış bir kitap varsa
ve
ödünç alanın adresi Z olarak biliniyosa,
Y ye X kitabı hakkında Zdeki yerine uyarı mesajı gönder.

Hepinize mutlu bir ay diliyorum, umarım kural motorları hakkında sıkmadan az da olsa bilgi sahibi yapmışımdır sizleri.

Kaynaklar: