Cumartesi, Mart 31, 2007

Sabahı Bekleyen Adamı bekleyen adam

Sabahı bekleyende kim olaki derseniz Hasta sabahı beklermiş efendim.
Hasta için sabah olmazmış bir türlü
Babamın geçirdiği ciddi bir rahatsızlık sebebiyle bir haftadır, "Sabahı Bekleyen Adamı bekleyen adam" durmundayım. Şifa dualarınıza muhtacız, bekleriz.

Cumartesi, Mart 10, 2007

Böcek Avı yahut Debugging





Debugging kelime manası Böceklerden arındırmadır. Hikayesi de 1945 de Mark II adlı Askeri devasa bilgisayarlarında programların düzgün çalışmasını engelleyen gerçek, fiziksel bir böcek bulan Dr. Grace Murray Hopper bilgisayar hatası anlamına da gelen "böcek" ("bug", "debugging", vs.) terimini de kültürümüze armağan etti. Yukardaki resim O ilk Bug'a ait.
Ben hata ayıklama diyeceğim. Ve Basit bir örnek vereceğim.

Genetik metodla 4 Bilinmiyenli Denklem Çözümü yazımın sonunda "FGA'nın Threadlı versiyonunu kullanın düz olan kısmında problem var." demiştim. Bu konuda FGA nın yazarına
e-posta attım. Bir süre sonra cevap geldi. özetle
"Hata ayıklamak için yeterli vaktim yok ama zannederim problem sizin yazdığınız fonksiyonlardaki hafıza yönetim kısımlarındadır."
diyordu. Bu durum da iş başa düşmüştü. Bir fırsat bulduğumda kolları sıvadım.
Yaptıklarım adım adım yazıyorum.

1) CodeBllocks 'da Denklem projesini açıyoruz.
2) Programın Build Target kısmını Debug olarak seçili olup olmadığına bakıyoruz Debug değilse Debug olarak seçip tekrar derliyoruz.
3) F8 ile yada Menüden Debug ->Start ile çalıştırıp Hata ayıklamaya başlıyoruz.
4) Program bir süre sonra Program received signal SIGSEGV, Segmentation fault
hatasını veriyor.

5) Backtrace 'i görmek siteyip istemediğimizi soruyor evet deyip CallStack penceresine geçiyoruz.

6) hata memcpy () fonksiyonunda oluşmuş. sebep olan satıra tıklayıp koda ulaşıyoruz
memcpy(child0, parent0, length * sizeof(GeneType));
7) Demek ki child0 yada parent0 işaretcilerinden -pointer- biri yada her ikisi NULL
8) Kodda biraz yukarıya çıkıp bakıyoruz ki child0'ın değeri new ile alınmış, hafızayı bukadar kısa süre de tüketmiş olamıyacağımızdan parent0 işaretçisine yöneliyoruz. parent işaretçisi değerini select fonksiyonundan alıyor.
9) CodeBlocks'un imkanlarından faydalanarak ilgili yere zıplayıveriyoruz.

10) Bir de ne görelim

inline GeneType *Population::select()
{
switch (select_type) {
case SELECT_UNIFORM:
return select_uniform();
default:
float choice = (float)rand() / RAND_MAX * total_score;
float position = 0;
for (int i = 0; i <>= choice)
return chromosome[i];
else
position += score[i];
}
return NULL;
}

switch'in default kısmında for döngüsüyle seçimin muhakkak yapılacağı varsayılmış seçim yapılmadığı durumda fonksiyon NULL değerini döndürüyor.

11) Emin olmak için return NULL; satırından önce puts("Returning NULL!!!"); satırını ekleyip. Menuden Debug->Stop Debugger ile debugger'ı durduruyoruz.

12) Yeniden, derleyip çalıştırıyoruz. Ve program çakılmadan önce bizim yazdığımız mesajı alıp
Emin oluyoruz. Vee Mutlu son.

Bundan sonrası için konuyu detayıyla yazıp Presto'ya mail attım.

ve cevabını buraya orjinal haliyle alıyorum.

the problem is the following:
sometimes the fitness function returns that small values around 10^-39 and so, if "choice" is maximum, "position + score[i]" never reaches choice this is due to a limit of binary representation of floating point
numbers on computers: they have to be approximated because not all
rational numbers can be represented
try to compile and execute this code and you'll know what I mean:


#include
using namespace std;

main()
{

float sum = 0.0;
for (int i = 0; i <> sum += 0.001;
if (sum == 1)
cout << "sum is exactly 1" <<>
else
cout << "sum is NOT exactly 1" <<>
cout << "sum is " <<>
cout << "but 1000 * 0.001 is " <<>
}


so, to avoid this problem, instead of return NULL in fga.hpp, select function, try to write return chromosome[n - 1]

this should fix the problem, since in the case that the floating point
representation fails it is because it doesn't completely reach choice,
but we know for sure that the last chromosome should be selected

I'll update the FGA code on sourceforge soon

thanks for your detailed info

kısaca fga.hpp de select kısmında sondaki
"return NULL;"
satırı yerine
return chromosome[n - 1];
kullanmamız problemi çözüyor.

Çarşamba, Mart 07, 2007

buruşuk pardesülü adam



ILS SONT EUX
...
buruk bir sabah
başlıyor acılı olduğu
açıkça anlaşılmayan
dünyada.
...
susuyor, söylemiyor bildiği tek şiiri
“güzel olan hiçbir şey hülasa edilemez”
demiş çünkü valéry.
çünkü serbest düşünme zamanı geçti artık
şimdi mesai saati
disiplin kurulunun toplantısı var
arşivde sicil belgeleri damgalanacak
tayinler imzaya girecek
teftişe gidecek generaller
rüya, okşayış, tevrat
gibi kelimeler
gündemin dışında.
yurttaşlar uygunadım çalışmalarıyla
söktüler kariha yarımküresini yerinden
bir pusula koydular açtıkları boşluğa
titreyen, korkak ibresiyle bu pusula
kuzeyi gösteriyor serbest
düşünme zamanlarında ;
safir bir göz görünce karıştırıyor yönü
tırnaklarını yiyor bakır bir
dudak ona yaklaşınca ;
cıvadan bir gözyaşı
bari olsun istiyor
bütün mesai boyunca.
buruşuk pardesülü adam dalgın
gittikçe daha dalgın, elinde cetvel
masada hesap makinesi, pusula
yetmiyor dibe dalmasına
bağlıyor kalın bir urganla beline
ağır bir sandık
salıyor kendini
yeşil yosunların
kırmızı balıkların
uçan kabarcıkların
derinliklerine
orada
bir sandık buluyor
yakutlar, altınlar, pırlantalar
adam dibe inmek için beline bağladığı
sandığını keşfediyor dibe ulaştığında.
öyleyse adamın eyvah ışıdı yüreği
eve dönmesine gerekçe
bulamıyacak bir daha.
...

Adamın pardesüsü'mü yüreğimi buruşuk olan?
Dibe dalması için programlamayı mı kullanıyor yapay zekayı mı ?.
Dibe ulaşabilecek mi ?
Ulaşırsa orda bir şeyler keşfedebilecek mi ?
Keşfettikleri evdekilerden ağır gelebilir mi ?
Eve dönmesine gerekçe bulamaması mümkün mü ?

Şimdi bütün bu sorulara cevap veremiyeceğim
çünkü serbest düşünme vakti geçti
şimdi artık mesai saati !

...
kimse görmüyor buruşuk pardesüsüyle bir babanın
kırılgan bir yelpaze olduğunu akşam eve girince
...

Cumartesi, Mart 03, 2007

Genetik metodla 4 Bilinmiyenli Denklem Çözümü

Genetik metoda epey bir ilgi var. Şu an itibarıyla Örnek Programlarım arasında ençok indirilen bu oldu. Genetik Programlamayla Bir İşlem = 395 (windows) + 72 (Linux) olmak üzere toplam 467 kere indirildi. Hatta Java versiyonunu da yazıldı.

Neyse biz konumuza geçelim geçenlerde bana bir mesaj geldi
... sizden genetik algoritma ile ilgili yardınızı istiyorum.Mezuniyet projem için genetik algoritma kullanilarak c veya c++ dort bilinmeyen denklemi cözen program yazmam gerekiyor ama nasil yapilacagi konusunda hic fikrim yok...
- Ahh Şöhreti kazibe -
Ben de yardımcı olmaya çalışacağımı bildirip konuyla ilgili detaylı bir mail atmasını istemiştim. cevap gecikmedi.
... o projeden vazgectim beni cok fazla zorlayacak. ... kare bulmaca (puzzle creator)yapmam daha dogru olucak ...
Bunun üzerine aslında korkulacak bir şey olmadığını göstermek ve bizim Fatih Presta'nın FGA
kütüphanesinin kullanımını anlatmak için basit bir örnek yazmaya karar verdim.

y=KatSayı1*x1+KatSayı2*x2+KatSayı3*x3+KatSayı4*x4+Sabit

denklemi 1 dereceden 4 bilinmeyenli bir denklemdir.
y=0 için x1,x2,x3,x4 değerlerinin bulunması lazım.

İşin teorik kısmını başkalarına bırakıp ben uygulamaya geçeceğim.

1) Bulmamız gereken 4 değer var. Kromozom uzunluğumuz 4 . Çözüm tamsayı olmaya bileceğine göre değişken tipi olarak da float seçiyoruz.
2) Olası çözümlerin kodlandığı bir çözüm gurubu oluşturmamız lazım - Population -

PopulationMT my_population(
number_of_threads, // Thread sayısı
number_of_chromosomes, // Kromozom Sayısı
length_of_chromosomes, // Kromozom Uzunluğu
my_fitness, // Uygunluk Fonksiyonu
NULL,
NULL,
my_crossover_operator, // Çaprazlama Fonksiyonu
my_mutate_chromosome, // Mutasyon Fonksiyonu
my_random_chromosome // Rasgele Kromozom Oluşturma Fonksiyonu
);


Göreceğiniz gibi Uygunluk Fonksiyonu, Çaprazlama Fonksiyonu, Mutasyon Fonksiyonu ve Rasgele Kromozom Oluşturma Fonksiyonu yazmamız lazım.

// Uygunluk Fonksiyonu
// Denklemin değerini hesaplıyoruz.
// Sonucun 0 olması kökün bulunması demektir.
// Sonucu biraz matematikle (0,1) arasına çekiyoruz
// 1'e ne kadar yakınsa çözüme o kadar uygun - sağlıklı -
float my_fitness(float *chromosome)
{
float *x=chromosome;
float y=kat[0]*x[0]+kat[1]*x[1]+kat[2]*x[2]+kat[3]*x[3]+Sabit;
if(y<0 br="br"> y=-1.0 *y;
y=1/(1+y);
return y;
}
// Çaprazlama Fonksiyonu
// FGA'nın Kendi sağladığı Fonksiyon da işimizi görebilir aslında
// Biz öğrenmek bakımından yazıyoruz
void my_crossover(float *chromosome1, float *chromosome2)
{
float tmp;
if(rand()%2){
// Tek Noktadan çaprazlama
//
1010 ----> 0110
//
0101 ----> 1001
tmp=chromosome1[0];
chromosome1[0]=chromosome2[0];
chromosome2[0]=tmp;
tmp=chromosome1[1];
chromosome1[1]=chromosome2[1];
chromosome2[1]=tmp;
}
else {
// İki Noktadan çaprazlama
//
1010 ----> 1111
//
0101 ----> 0000
tmp=chromosome1[1];
chromosome1[1]=chromosome2[1];
chromosome2[1]=tmp;
tmp=chromosome1[2];
chromosome1[2]=chromosome2[2];
chromosome2[2]=tmp;

}

}


// Mutasyon Fonksiyonu
void my_mutate_chromosome(float *chromosome)
{
int a;
int b;
float tmp;
a = rand() % 4;
do{
b = rand() % 4;
}while(a==b);

if(rand()%2)
tmp=1.001;
else
tmp=0.999;
chromosome[a]=chromosome[a]*tmp;

if(rand()%2)
tmp=1.001;
else
tmp=0.999;
chromosome[b]=chromosome[b]*tmp;
}

// Rasgele Kromozom Oluşturma Fonksiyonu
// Arama yapacağımız aralığı seçiyoruz ben (-20,20) aralığını seçtim.
// Bütün X değerleri bu aralıkta seçiliyor.
void my_random_chromosome(float *chromosome)
{
float *x=(float *)chromosome;
for(int i=0; i<4 i="i">


Artık Gurubumuzu oluştura biliriz.

PopulationMT my_population(10, 400, 4, my_fitness, NULL, NULL, my_crossover, my_mutate_chromosome, my_random_chromosome);
3) gerisi Bir döngü içinde yeterince iyi sonuca ulaşana kadar.
yada belli kuşak sayısına kadar, işleme devam etmek.
Bunun için önce cycle fonksiyonu çağrılıyor.
sonra ulaşılan en iyi sonucu almak için
get_all_time_best_score fonksiyonu çağrılıyor.


while ((1.0-score)>0.00001) {
my_population.cycle();
score = my_population.get_all_time_best_score();
}
hepsi bu kadar.
Gördüğünüz gibi çekinilecek hiç bir şey yok. Bence Kare Bulmaca hazırlamaktan daha kolay ;)
Indirmek için : Download Denklem

Not:
1) FGA'nın Threadlı versiyonunu kullanın düz olan kısmında problem var. POSIX thread konusu daha önceki yazımda anlatmıştım.

2) Konuyla ilgili sorularınız olursa, Biz buradayız bekleriz.