PipedStream

Robot porjesinde RS232 üzerinden gönderilen komutlar bazen gitmiyor. Program başka bir iş yaparken serialport'a veya outputstream'a erişemiyoruzdur, timeout oluyordur vs. diye Sender için da thread açalım dedik.

Thread'lar arası data (buffer, stream ne denirse artık) göndermek için PipedStream tipleri varmış.

PipedOutputStream out = new PipedOutputStream();
PipedInputStream in = new PipedInputStream(out);
Sonra bunları farklı thread'larda
(OutputStream) out
(InputStream) in
Şeklinde kullanıyorsunuz istediğiniz gibi.
 Ama out.write(byte[])    in.read(byte[]) kullanımı yine birbirlerini block'layarak çalışacağı için bize bir yararı olmuyor (Götoş Sun).
Bunun yerine naapıyoruz?
out.write(byte []) olduğu gibi kalıyor. ve
<script src="http://gist.github.com/345368.js"> </script>
Kodunun çalışması için dua ediyoruz... İki komut arka arkaya geldiğinde birbirlerini ezecek gibi duruyor, ama hadi bakalım allah büyüktür...

ArrayList ve Local Type Casting Check

Evet java sucks yazı dizimize devam ediyoruz...

ArrayList src,dest;
...
while( id < numberX) {
   MyClass m = src.get(id++); 
   // Bundan sonra başka işlemlerde olduğunu düşünün,
   // local variable olayı bu yüzden.
   dest.add(m);
}

Şimdi bu şekilde bir kullanımda compile time'da type check yapılıyor, pek şukela. Ama JVM, runtime'da da yapıyor aynı işi. Sonuçta MyClass tipinden mi diye kontrol edilirken boşuna vakit kaybı.

MyClass yerine Object kullanınca typeCheck'den kurtuluyorsunuz, ama compile olmuyor (Eheheehe).

Yani elimizde local variable optimizasyou yapamayan bir compiler var ve insanlar bunu bilmiyor/umursamıyor ya da ben biraz malım, kafam basmıyor bu konulara ?  Cevap vermeyin bu soruya

Genetik Algoritma ile Traveling Salesman

Program "pure" genetik algoritma üzerinde çalıştığından, 2-opt, greedy vs. bir heuristic kullanan genetik algoritmaya göre daha yavaş sonuca ulaşır. Bu algoritmanın genel adımları şöyle:

  1. Tüm şehirlerden bir kez geçilen bir "rota" oluştur. Bu işlemi genetik algoritma X nüfus üzerinde çalışacaksa X kez tekrarla. Tabii aynı rotanın 2 kez olmaması için gerekli önlemleri de almak gerek. Bu rota bizim kromozomumuz olacak.
  2. Rulet tekeri yöntemi veya sıralama seçimi kullanarak 2 rotayı ebeveyn olarak seç. Kısaca daha iyi durumdaki yollara daha yüksek olasılık vererek 2 adet rota seçilecek.
  3. Seçilen ebeveyn kromozomlar özel bir yöntemle çaprazlanacak. Normal çaprazlama TSP'de işe yaramıyor çünkü bir kromozomda aynı şehir iki kez bulunmamalı. Keyword: Order-based crossover
  4. Oluşan çocukların küçük bir ihtimal mutasyona uğrama şansı var. Mutasyon işlemi random iki şehrin yerinin değiştirilmesi şeklinde olabilir.
  5. Çocuklar en kötü iki rota yerine geçiyor. Böylece her jenerasyonda nüfusun iyiye gitmesi sağlanmaya çalışılıyor.
Burada bir rotanın iyi mi kötü mü olduğu değerlendirilirken (fitness function) o rotanın toplam uzunluğu dikkate alınıyor. Uzunsa kötü, kısaysa iyi. 20 şehir içeren bir haritada bu algoritma çalıştırılırken iyi bir sonuç alabilmek için 100000 nüfusun 1000 jenerasyon boyunca yaşaması gerekiyor. 28 saniye sürüyor çalışması. Multi-threaded kodlanırsa düşer tabii bu süre. Bir de benim dandik kodlamış olma ihtimalim var :)

Mutasyonu yüzde 10 yapınca, yüzde 5'e göre sonuç kötüleşiyor. Yani mutasyon olayını abartmamak gerekiyor.

Burada önemli bir faktör, heuristic kullanılsaydı daha az nüfus ve daha kısa bir jenerasyon süresi sonunda aynı veya daha iyi bir sonuca ulaşmak mümkündür.

Media_httpmediatumblr_pydaq

Sonraki yazı Paralel Tepe Tırmanma (Local Beam Search) ile çözümü anlatacak.

Tek .Jar Dosyası Olarak Dağıtım Hazırlamak

Referans jar’lar ve native kütüphaneleri (.so, .dll vs.) oluşturduğunuz .JAR paketine nasıl dahil ediyorsunuz?

Normalde jar referanslar (netbeans,ant,eclipse bunu yapıyor) /lib klasörü altına kopyalanır. Native’ler için hazır gelen bir seçenek yok ama:

<property name="natives.dir" value="lib/native/win32-x86/"/>
<target name="win-native" depends="jar"
<copy todir="${dist.jar.dir}">
<fileset dir="${natives.dir}"  includes="*.dll"/>
</copy>
</target>
gibi gibi ant target’leri yazılabilir. Ama sonuçta yine de,
| jarname.jar
| /LIBS
| | 1.jar
| | 2.jar
| | 3.jar
| 4.dll
| 5.dll
| log4j.properties
şeklinde .jar paketimiz dışında oluşmuş bir klasör yapımız olur. Aranızda hiç yarım saat bir programı çalıştırmaya uğraşan, sonuçta sorunun yanlış tanımlanan Classpath (JVM’ye -D switch’i gerekliymiş…) olduğunu bulan oldu mu (Java sucks-1)? Tek bir paket oluşturmayı bu nedenle istiyorum.

Sorun Java Classloader’ın .jar paketleri içerisindeki .jar’lara nasıl ulaşacağını bilmemesi. Classpath’daki referanslar mutlaka .Jar dosyası dışında olmalı (Java sucks-2). Aynı şekilde runtime’da native lib’ler yüklenirken jar paketi içine ulaşamıyoruz(Java sucks-3).

Bunları bu kadar yazdım belki başka çözümler vardır da haber verirsiniz, benim bulduğum çok da mantıklı olmayabilir: One-Jar, Netbeans Wiki - PackagingADistributableJavaApp – OneJar. Program çalıştırılmadan önce referans kütüphanelerini otomatik olarak extract ediyor. Sonrasında siliyor.

Bazı notlar:
“Adding the OneJar Manifest” adımında “Class-Path:” için bütün gerekli .jar’ları listelemenize gerek yok, en azından Netbeans kullanıyorsanız ve /lib altında bulunuyorlarsa sorun olmuyor.

Klasör isimlerini değiştirmeyi unutmayın, ne bileyim başka söyleyecek bir şey aklıma gelmedi.