clc; frame = javax.swing.JFrame; frame.setSize(300,300); frame.setTitle('Hello'); frame.setLocationRelativeTo([]); frame.setLayout([]); button1 = javax.swing.JButton('TEST'); button1.setBounds(20,20, 120,30 ); label = javax.swing.JLabel(''); label.setBounds(20,60, 120,30); set(button1, 'MouseClickedCallback' , ... @(h,e)(set(label, 'text', ['kalian luar biasa...! ',... num2str(randi(11,1))]))); frame.add(label); frame.add(button1); frame.show;Yang hasil eksekusinya adalah sebagai berikut:
Sesungguhnya shalat itu mencegah dari (perbuatan-perbuatan) keji dan mungkar
Q.S. Al-'Ankabut Ayat 45
Sunday, May 17, 2015
Menggunakan komponen java swing dari MATLAB
Saturday, March 28, 2015
Mengatur Area Blur Pada Image Dengan Mouse Scroll di MATLAB
% test window scroll function untuk memblur gambar. Gunakan mouse scroll % untuk memperluas atau mempersempit lokasi blur function testWindowScroll clear all; clc; f = figure('WindowScrollWheelFcn',@sliderHandle,'menubar', 'none' ); ax = axes('parent', f, 'units', 'pix' ); im = (imread('gambar 1/lion-test.jpg')); % disesuaikan imshow(im,'parent', ax); sizeImage = size(im); w = sizeImage(2); h = sizeImage(1); halfW = double(w)/2; halfH = double(h)/2; maxD = min(w,h)/2; initD = 100; blurImage(initD); function sliderHandle(src, event) m = get(0, 'PointerLocation'); xMouse = m(1); yMouse = m(2); posFig = get(f, 'position'); xFig = posFig(1); yFig = posFig(2); widthFig = posFig(3); heightFig = posFig(4); if (xMouse > xFig ) && (yMouse > yFig ) && ... (xMouse < xFig + widthFig ) && ... (yMouse < yFig + heightFig ) if event.VerticalScrollCount < 0 % up initD = initD + 3; elseif event.VerticalScrollCount > 0 % down if initD - 3 > 0 initD = initD - 3; end end blurImage(initD); end end function blurImage(d) if d < maxD [xx,yy] = ndgrid(( 1:h )-halfH , ( 1:w ) - halfW ) ; mask = uint8( ( xx.^2 + yy.^2 ) > d^2); G = fspecial('disk', 10); cropped = uint8(zeros(sizeImage)); cropped(:,:,1) = roifilt2(G ,im(:,:,1) , mask ); cropped(:,:,2) = roifilt2(G ,im(:,:,2) , mask ); cropped(:,:,3) = roifilt2(G ,im(:,:,3) , mask ); imshow( cropped ); drawnow; end end endDi mana video implementasinya di komputer saya adalah sebagai berikut
Friday, March 20, 2015
Cara Sorting Cell di MATLAB
clear all; clc; % test sorting dari cell M = cell(4,2); M{1,1} = 'mawar'; M{1,2} = 23; M{2,1} = 'Anggrek' ; M{2,2} = 11; M{3,1} = 'Durian'; M{3,2} = 45; M{4,1} = 'Benalu'; M{4,2} = 222; % sorting berdasarkan jarak N = sortrows(M,2); disp(M); disp(N); % output % 'mawar' [ 23] % 'Anggrek' [ 11] % 'Durian' [ 45] % 'Benalu' [222] % % 'Anggrek' [ 11] % 'mawar' [ 23] % 'Durian' [ 45] % 'Benalu' [222]
Monday, February 23, 2015
Memahami Epicycle
Dahulu kala, sekitar 1000 tahun sebelum masehi orang-orang masih berpatokan pada konsep geosentris yakni memposisikan bumi sebagai pusat alam semesta. Data-data pergerakan planet pada waktu itu (yang diamati melalui teleskop) sudah banyak tersedia. Ini kemudian coba dimodelkan untuk mencari tahu bagaimana lintasan planet-planet relatif terhadap bumi sebagai pusat tata surya (alam semesta). Namun ternyata data-data tersebut jika ditafsirkan dengan konsep geosentris, akan terlihat bahwa gerakan planet-planet yang diketahui pada saat itu, tampak sangat tidak beraturan. Dan ini sangat bertentangan dengan teologi bahwa alam semesta diciptakan oleh Tuhan yang menyukai keteraturan.
Datang lah seorang Ptolemeus yang memberikan sebuah penjelasan bahwa lintasan planet-planet tersebut dapat dipandang sebagai lintasan titik dalam dalam geometri epicycle. Ini mampu menjelaskan keteraturannya yang diasumsikan berdasarkan kehendak Tuhan. Ptolemeus dan ilmuan-ilmuan sesudahnya kemudian berasumsi bahwa Tuhan sangat menyukai bentuk lingkaran.
Pada tulisan selanjutnya saya akan membuktikan bahwa dengan epicycle, kita bukan hanya bisa men-track lintasan planet dengan konsep geosentris, akan tetapi lintasan apa saja yang berbentuk kurva tertutup. Ini tidak lain merupakan implikasi dari analisis fourier yang secara kasar menegaskan bahwa semua fungsi perodik bisa dinyatakan sebagai penjumlahan dari fungsi-fungsi sinusoidal.
Saya punya project di github tentang bagaimana epicycle dapat menghasilkan sebuah lintasan yang tidak teratur namun tetap berbentuk kurva tertutup.
Tuesday, December 23, 2014
Plot Fungsi Gaussian Dengan MATLAB
\begin{equation} f(x) = a \exp \left ( - \frac{(x - b )^2 }{ 2 \, c^2 } \right ) \label{pers1} \end{equation} Dengan $a$, $b$, dan $c$ konstanta real sembarang. Untuk memahami karakteristik persamaan \ref{pers1} di atas, Anda dapat mencoba potongan script berikut
clear all; clc; % test sorting dari cell M = cell(4,2); M{1,1} = 'mawar'; M{1,2} = 23; M{2,1} = 'Anggrek' ; M{2,2} = 11; M{3,1} = 'Durian'; M{3,2} = 45; M{4,1} = 'Benalu'; M{4,2} = 222; % sorting berdasarkan jarak N = sortrows(M,2); disp(M); disp(N); % output % 'mawar' [ 23] % 'Anggrek' [ 11] % 'Durian' [ 45] % 'Benalu' [222] % % 'Anggrek' [ 11] % 'mawar' [ 23] % 'Durian' [ 45] % 'Benalu' [222]
Friday, December 19, 2014
Perkalian matriks secara parallel
Pada posting ini, saya akan menyajikan kelanjutan posting saya sebelumnya, yakni posting mengenai perkalian matriks secara rekursi. Namun dalam posting ini saya akan menekankan pada aspek manfaatnya.
Orang-orang bisa berkata buat apa kita melakukan rekursi jika hasilnya sama saja? Jawabnya ada di posting kali ini.
Dalam rilis terbaru bahasa Java yakni Java 7 telah diperkenalkan konsep paralellisme dengan cara yang lebih modern dibandingkan sebelumnya. Yakni dengan memasukkan beberapa class baru ke dalam Java Standard Library yang khusus untuk menangani keperluan parallelisme. Dua class yang dimaksud adalah RecursiveAction dan RecursiveTask. Ada sebuah posting menarik dari oracle yang membahas mengenai masalah ini.
Pada kesempatan kali ini saya akan mengekspose fitur yang disajikan class yang dimaksud untuk keperluan meningkatkan efisiensi dalam perkalian matriks. Mekanismenya sudah dijelaskan pada posting saya sebelumnya (tentang perkalian matriks secara rekursi). Hanya dalam posting ini, matriks C yang sudah dipecah ke dalam sub-sub-sub… matriks C, elemennya di-isi secara parallel. Akibatnya adalah waktu eksekusi bisa berkurang hingga setengahnya. Jadi ketika secara normal dia membutuhkan waktu 10 detik, maka dengan parallelisme dia hanya membutuhkan waktu 5 detik. Saya sudah memposting di github project saya tersebut, dan Anda bisa mencobanya di rumah. Mudah-mudahan hasilnya tidak beda jauh dari apa yang saya peroleh.
Dalam hasil percobaan saya, dilakukan perkalian dua buah matriks yakni matriks A dengan ukuran (1000,600) dan matriks B dengan ukuran (600,9000) di mana waktu eksekusi dengan cara tradisional membutuhkan waktu 143 detik, sementara waktu eksekusi dengan cara parallel membutuhkan waktu 73 detik.
Wednesday, December 17, 2014
Perkalian Matriks Secara Rekursi
Dalam kesempatan kali ini saya akan memberikan sedikit pencerahan tentang bagaimana mengalikan matriks secara rekursi.
Di dalam dunia pemrograman, rekursi didefenisikan sebagai pemecahan masalah dengan cara membaginya ke dalam sub bagian yang lebih kecil. Hal ini ditandai dengan adanya panggilan terhadap fungsi/method dari dalam method/fungsi itu sendiri.
Kali ini saya akan memberikan contoh bagaimana operasi perkalian matriks bisa dilakukan secara rekursi. Artinya ketimbang melakukan iterasi satu per satu terhadap semua elemen matriks untuk memperoleh hasil akhir. Maka dengan rekursi, kita melakukan perkalian secara simultan terhadap kelompok-kelompok elemen dari matriks tersebut.
Metodenya adalah dengan membagi matriks ke dalam 4 kuadran, yang masing-masing bagian akan dibagi lagi menjadi 4 kuadran secara berkelanjutan, hingga dijumpai base case. Pada base case ini baru kemudian dilakukan perhitungan secara langsung. Base-case diperlukan dalam rekursi, karena jika tidak ada base-case, maka akan terjadi pemanggilan berulang-ulang tanpa henti yang berakibat alokasi berlebihan terhadap memori stack pada komputer. Dan ujung-ujungnya terjadi stack-overflow.
Prinsip kerjanya adalah, ketika matriks A dengan dimensi (m,n) dengan m menyatakan jumlah baris dan n jumlah kolom dikalikan dengan matriks B dengan dimensi (o,p), maka matriks hasil akan berdimensi (m,p). Jadi yang kita lakukan adalah menerapkan rekursi dalam pengisian elemen dari matriks hasil tadi (katakanlah matriks C). Perhatikan potongan script berikut
Dalam potongan script di atas, kita melakukan pengisian elemen ke (i,j) pada matriks C dengan mengalikan elemen pada baris ke-i matriks A dengan kolom ke-j matriks B lantas menjumlahkannya. Di sini kuncinya! Jadi dengan melakukan rekursi terhadap baris dan kolom matriks C maka kita tidak perlu lagi pusing memikirkan bagaimana mengkondisikan elemen matriks B dan elemen dari matriks A untuk keperluan perkalian matriks secara rekursi. Yang perlu kita pikirkan hanya proses pengisian elemen dari matriks C tadi.
public void multiply(int barisA, int kolomB) {
int sum = 0;
for (int k = 0; k < dimensiTengah; k++) {
sum += matriksA[barisA][k] * matriksB[k][kolomB];
}
matriksC[barisA][kolomB] = sum;
}
Kita akan melakukan proses pengisian tersebut dengan membagi matriks C ke dalam 4 kuadran secara rekursi sampai diperoleh base case. Base case dijumpai ketika jumlah baris serta jumlah kolom dari sub matriks C---matriks yang diperoleh dari pemecahan matriks C ke dalam 4 kuadran tadi (walaupun hakikatnya dalam memori hanya matriks C juga)---telah melampaui ambang tertentu. Perhatikan potongan script berikut.
public void compute() {Dalam potongan di atas, ketika jumlah baris dari sub-matriks C dan jumlah kolomnya masih lebih besar dari ambang, maka bagi lagi secara rekursi menjadi sub-sub matriks berikutnya (dalam 4 kuadran). Ketika jumlah baris masih lebih besar dari ambang, bagi sub-matriks C ke dalam dua sub-matriks berikutnya dalam arah horizontal (bagi baris-barisnya ke dalam dua bagian). Sementara jika jumlah kolomnya masih lebih besar dari ambang, maka bagi sub-matriks C dalam arah vertikal (bagi kolom-kolomnya menjadi dua bagian).
int limit = 10;
int limitKolom = (int) (Math.floor( ((awalKolom - akhirKolom) / 2)));
int limitBaris = (int) (Math.floor( ((akhirBaris - awalBaris) / 2)));
int halfBaris = awalBaris + limitBaris;
int halfKolom = awalKolom + limitKolom;
if (limitKolom <= limit && limitBaris <= limit) {
computeDirectly(awalBaris, akhirBaris, awalKolom, akhirKolom);
return;
} else if (limitBaris <= limit && limitKolom > limit) { // split over column
RecursiveMatrixMultiplication p2 = new RecursiveMatrixMultiplication(matriksA, matriksB,
matriksC, dimensiTengah, awalBaris, akhirBaris, awalKolom,
halfKolom);
RecursiveMatrixMultiplication p4 = new RecursiveMatrixMultiplication(matriksA, matriksB,
matriksC, dimensiTengah, awalBaris, akhirBaris, halfKolom,
akhirKolom);
invokeAll(p2, p4);
} else if (limitKolom <= limit && limitBaris > limit) { // split over
// row
RecursiveMatrixMultiplication p1 = new RecursiveMatrixMultiplication(
matriksA, matriksB,matriksC,
dimensiTengah,
awalBaris, halfBaris,
awalKolom, akhirKolom);
RecursiveMatrixMultiplication p3 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC,
dimensiTengah,
halfBaris, akhirBaris,
awalKolom, akhirKolom);
invokeAll(p1, p3);
} else if (limitKolom > limit && limitBaris > limit) { // split to 4 quadran
RecursiveMatrixMultiplication p1 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC, dimensiTengah,
awalBaris, halfBaris,
awalKolom, halfKolom); // kuadran 1
RecursiveMatrixMultiplication p2 = new RecursiveMatrixMultiplication(
matriksA, matriksB,matriksC, dimensiTengah,
halfBaris, akhirBaris,
awalKolom, halfKolom); // kuadran 2
RecursiveMatrixMultiplication p3 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC , dimensiTengah,
awalBaris, halfBaris,
halfKolom, akhirKolom); // kuadran 3
RecursiveMatrixMultiplication p4 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC, dimensiTengah,
halfBaris, akhirBaris,
halfKolom, akhirKolom); // kuadran 4
invokeAll(p1, p2, p3, p4);
}
}
Ketika dijumpai base-case, yakni ketika jumlah kolom dan jumlah baris dari sub-sub-sub-sub… matrik C lebih kecil dari nilai ambang, maka lakukan perkalian elemen-elemen matriks A dan matriks B untuk mengisi elemen-elemen dari sub-sub-sub… matriks C tersebut.
Secara keseluruhan kode yang digunakan adalah sebagai berikut (di dalamnya terdapat juga method untuk mengecek kevalidan operasi yakni dengan membandingkannya dengan perkalian secara konvensional, tanpa rekursi).
package algo.test.multiply;
import java.util.Random;
public class RecursiveMatrixMultiplication {
int[][] matriksA;
int[][] matriksB;
int[][] matriksC;
int awalBaris;
int awalKolom;
int akhirBaris;
int akhirKolom;
int dimensiTengah;
public RecursiveMatrixMultiplication(int[][] matriksA, int[][] matriksB,
int[][] matriksC, int dimensiTengah, int awalBaris, int akhirBaris,
int awalKolom, int akhirKolom) {
this.matriksA = matriksA;
this.matriksB = matriksB;
this.matriksC = matriksC;
this.awalBaris = awalBaris;
this.awalKolom = awalKolom;
this.akhirBaris = akhirBaris;
this.akhirKolom = akhirKolom;
this.dimensiTengah = dimensiTengah;
}
public void multiply(int barisA, int kolomB) {
int sum = 0;
for (int k = 0; k < dimensiTengah; k++) {
sum += matriksA[barisA][k] * matriksB[k][kolomB];
}
matriksC[barisA][kolomB] = sum;
}
private void computeDirectly(int awalBaris, int akhirBaris, int awalKolom,
int akhirKolom) {
for (int i = awalBaris; i < akhirBaris; i++) {
for (int j = awalKolom; j < akhirKolom; j++) {
multiply(i, j);
}
}
}
public void invokeAll(RecursiveMatrixMultiplication...matrixMultiplications ){
for(RecursiveMatrixMultiplication m: matrixMultiplications){
m.compute();
}
}
public void invoke(){
invokeAll(this);
}
public void compute() {
int limit = 10;
int limitKolom = (int) (Math.floor( ((awalKolom - akhirKolom) / 2)));
int limitBaris = (int) (Math.floor( ((akhirBaris - awalBaris) / 2)));
int halfBaris = awalBaris + limitBaris;
int halfKolom = awalKolom + limitKolom;
if (limitKolom <= limit && limitBaris <= limit) {
computeDirectly(awalBaris, akhirBaris, awalKolom, akhirKolom);
return;
} else if (limitBaris <= limit && limitKolom > limit) { // split over column
RecursiveMatrixMultiplication p2 = new RecursiveMatrixMultiplication(matriksA, matriksB,
matriksC, dimensiTengah, awalBaris, akhirBaris, awalKolom,
halfKolom);
RecursiveMatrixMultiplication p4 = new RecursiveMatrixMultiplication(matriksA, matriksB,
matriksC, dimensiTengah, awalBaris, akhirBaris, halfKolom,
akhirKolom);
invokeAll(p2, p4);
} else if (limitKolom <= limit && limitBaris > limit) { // split over
// row
RecursiveMatrixMultiplication p1 = new RecursiveMatrixMultiplication(
matriksA, matriksB,matriksC,
dimensiTengah,
awalBaris, halfBaris,
awalKolom, akhirKolom);
RecursiveMatrixMultiplication p3 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC,
dimensiTengah,
halfBaris, akhirBaris,
awalKolom, akhirKolom);
invokeAll(p1, p3);
} else if (limitKolom > limit && limitBaris > limit) { // split to 4 quadran
RecursiveMatrixMultiplication p1 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC, dimensiTengah,
awalBaris, halfBaris,
awalKolom, halfKolom); // kuadran 1
RecursiveMatrixMultiplication p2 = new RecursiveMatrixMultiplication(
matriksA, matriksB,matriksC, dimensiTengah,
halfBaris, akhirBaris,
awalKolom, halfKolom); // kuadran 2
RecursiveMatrixMultiplication p3 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC , dimensiTengah,
awalBaris, halfBaris,
halfKolom, akhirKolom); // kuadran 3
RecursiveMatrixMultiplication p4 = new RecursiveMatrixMultiplication(
matriksA, matriksB, matriksC, dimensiTengah,
halfBaris, akhirBaris,
halfKolom, akhirKolom); // kuadran 4
invokeAll(p1, p2, p3, p4);
}
}
/*
* bandingkan matriksA dan matriksB..
* jika semua elemennya sama, maka kembalikan matriksC yang isinya semua 1...
* jika ada elemen yang beda isi elemen matriksC dengan 0
*/
public static int [][] compareMatriks(int [][] matriksA, int[][] matriksB){
int C[][] = new int [matriksA.length][matriksA[0].length];
for( int i=0; i < matriksA.length ;i++){
for(int j=0; j < matriksA[0].length ;j++){
if(matriksA[i][j] == matriksB[i][j]){
C[i][j] = 1;
}else{
C[i][j] = 0;
}
}
}
return C;
}
/*
* sebagai pembanding untuk mengetahui operasi berjalan dengan benar..
* yakni lakukan perkalian secara Langsung.. tanpa rekursive...
*/
public static int[][] multiplyDirectly(int [][] matriksA, int[][] matriksB){
int result[][] = new int[matriksA.length][matriksB[0].length];
for(int i= 0; i< matriksA.length ;i++){
for(int j=0; j< matriksB[0].length ;j++){
int sum = 0;
for( int k = 0 ; k < matriksB.length ;k ++){
sum += matriksA[i][k] * matriksB[k][j];
}
result[i][j] = sum;
}
}
return result;
}
/*
* generate random matriks
*/
public static int [][] generateMatriks(int baris, int kolom){
int matriks[][] = new int[baris][kolom];
Random rn = new Random();
for(int i=0; i < matriks.length ; i++){
for( int j=0; j < matriks[0].length ;j++){
matriks[i][j] = rn.nextInt(100);
}
}
return matriks ;
}
/*
* pretty print matrix
*/
public static void printMatriks(int [][] matriks) {
for (int i = 0; i < matriks.length; i++) {
for (int j = 0; j < matriks[0].length; j++) {
System.out.print(matriks[i][j] + "|");
}
System.out.print("\n");
}
System.out.print("\n");
}
public int[][] getResult() {
return matriksC;
}
public static void main(String[] args){
int[][] matriksA = generateMatriks(300, 200);
int[][] matriksB = generateMatriks(200, 500);
long now = System.nanoTime();
int[][] matriksResultA = multiplyDirectly(matriksA, matriksB);
now = (System.nanoTime() - now) / 1000000;
long now1 = System.nanoTime();
int[][] matriksC = new int[matriksA.length][matriksB[0].length];
RecursiveMatrixMultiplication parallel = new RecursiveMatrixMultiplication(matriksA, matriksB, matriksC,
matriksB.length, 0 , matriksC.length, 0, matriksC[0].length);
parallel.invoke();
int[][] matriksResultB = parallel.getResult();
now1 = (System.nanoTime() - now1) / 1000000;
int[][] hasilCompare = compareMatriks(matriksResultA, matriksResultB);
printMatriks(hasilCompare);
System.out.println(now);
System.out.println(now1);
System.out.println("FINISH");
}
}
Sunday, December 14, 2014
Penjelasan Algoritma Genetik
Saya akan memberikan contoh kasus kegunaan algoritma genetik dalam memecahkan persoalan optimisasi traveling salesman. Pernyataan traveling salesman adalah terdapat kumpulan kota yang berjarak tertentu satu sama lain. Dan kita diharuskan untuk mengunjungi seluruh kota-kota tersebut satu persatu di mana satu kota hanya boleh dikunjungi sekali. Kemudian dihitung rute mana yang menghasilkan jarak tempuh yang paling singkat. Dengan metode brute force (mencari semua kemungkinan) tentu saja akan sangat tidak efisien. Misalnya saja ketika jumlah kota nya ada 4, maka ada 24 kemungkinan rute yang bisa ditempuh, dan kita harus mencari tahu jarak pada semua rute tersebut. Bagaimana kalo kotanya ada 100, kan tidak mungkin.
Untuk implementasi algoritma genetik dari kasus ini sudah diberikan oleh sebuah blog yang beralamat di sini. Jadi saya tidak perlu mengulangi apa yang disampaikan pada blog tersebut. Intinya adalah terdapat kota yang harus dikunjungi dengan peta sebagai berikut:
Source dari blog tersebut juga sudah saya host di github.
Dari keseluruhan source code tersebut, saya akan memberikan sedikit penjelasan mengenai mana bagian yang paling penting atau yang menjadi bagian inti dari algoritma genetik dalam menyelesaikan persoalan tersebut. Yakni dapat dilihat pada potongan script berikut
package com.fjr.genetic.main;
public class GA {
/* GA parameters */
private static final double mutationRate = 0.015;
private static final int tournamentSize = 5;
private static final boolean elitism = true;
// Evolves a population over one generation
public static Population evolvePopulation(Population pop) {
Population newPopulation = new Population(pop.populationSize(), false);
// Keep our best individual if elitism is enabled
int elitismOffset = 0;
if (elitism) {
newPopulation.saveTour(0, pop.getFittest());
elitismOffset = 1;
}
// Crossover population
// Loop over the new population's size and create individuals from
// Current population
for (int i = elitismOffset; i < newPopulation.populationSize(); i++) {
// Select parents
Tour parent1 = tournamentSelection(pop); // bagian 1
Tour parent2 = tournamentSelection(pop);
// Crossover parents
Tour child = crossover(parent1, parent2);
// Add child to new population
newPopulation.saveTour(i, child);
}
// Mutate the new population a bit to add some new genetic material
for (int i = elitismOffset; i < newPopulation.populationSize(); i++) {
mutate(newPopulation.getTour(i)); // bagian 2
}
return newPopulation;
}
// Applies crossover to a set of parents and creates offspring
public static Tour crossover(Tour parent1, Tour parent2) {
// Create new child tour
Tour child = new Tour();
// Get start and end sub tour positions for parent1's tour
int startPos = (int) (Math.random() * parent1.tourSize()); // bagian 3
int endPos = (int) (Math.random() * parent1.tourSize());
// Loop and add the sub tour from parent1 to our child
for (int i = 0; i < child.tourSize(); i++) { // bagian 4
// If our start position is less than the end position
if (startPos < endPos && i > startPos && i < endPos) {
child.setCity(i, parent1.getCity(i));
} // If our start position is larger
else if (startPos > endPos) {
if (!(i < startPos && i > endPos)) {
child.setCity(i, parent1.getCity(i));
}
}
}
// Loop through parent2's city tour
for (int i = 0; i < parent2.tourSize(); i++) { // bagian 5
// If child doesn't have the city add it
if (!child.containsCity(parent2.getCity(i))) {
// Loop to find a spare position in the child's tour
for (int ii = 0; ii < child.tourSize(); ii++) {
// Spare position found, add city
if (child.getCity(ii) == null) {
child.setCity(ii, parent2.getCity(i));
break;
}
}
}
}
return child;
}
// Mutate a tour using swap mutation
private static void mutate(Tour tour) { //bagian 6
// Loop through tour cities
for(int tourPos1=0; tourPos1 < tour.tourSize(); tourPos1++){
// Apply mutation rate
if(Math.random() < mutationRate){
// Get a second random position in the tour
int tourPos2 = (int) (tour.tourSize() * Math.random());
// Get the cities at target position in tour
City city1 = tour.getCity(tourPos1);
City city2 = tour.getCity(tourPos2);
// Swap them around
tour.setCity(tourPos2, city1);
tour.setCity(tourPos1, city2);
}
}
}
// Selects candidate tour for crossover
private static Tour tournamentSelection(Population pop) { // bagian 7
// Create a tournament population
Population tournament = new Population(tournamentSize, false);
// For each place in the tournament get a random candidate tour and
// add it
for (int i = 0; i < tournamentSize; i++) {
int randomId = (int) (Math.random() * pop.populationSize());
tournament.saveTour(i, pop.getTour(randomId));
}
// Get the fittest tour
Tour fittest = tournament.getFittest();
return fittest;
}
}
Pada keterangan yang ditandai dengan bagian 1 dari potongan script di atas, akan dilakukan pemilihan 5 anggota populasi secara acak dari seluruh populasi awal untuk diseleksi. Seleksi kemudian akan mencari rute yang memiliki jarak tempuh paling singkat. Hasilnya kemudian akan dilakukan penerapan operasi crossover yang akan menghasilkan anggota populasi anak untuk dimasukkan ke dalam populasi dari generasi berikutnya. Hal ini di-loop untuk seluruh total populasi. Bagian 2 menandakan operasi mutasi terhadap seluruh anggota populasi baru generasi berikutnya (populasi anak). Bagian 3 merupakan sub-bagian dari operasi crossover. Di mana akan dipilih secara acak pada bagian string/list/kromosom dari anggota populasi induk (yakni dua anggota populasi induk) yang ditandai sebagai bagian awal (start) dan bagian akhir (end) dari kromosom untuk diterapkan operasi crossover. Untuk bagian elemen string/list/kromosom ke-i dari rute yang masuk dalam rentang start sampai ke end dengan start < end, maka set element ke-i dari kromosom anak sebagai elemen dari kromosom rute induk 1. Jika end < start, maka set elemen ke-i dari kromosom anak sebagai bagian dari kromosom induk 1 jika nilai i tersebut berada di luar rentang start sampai end. Bagian 5 menandakan operasi untuk mengisi elemen dari kromosom anak dengan mengambil dari element kromosom rute induk 2. Yakni dengan mengisi bagian yang belum di-isi oleh elemen dari rute induk 1
Bagian 6 merupakan implementasi dari operasi mutasi di mana akan akan diadakan pertukaran letak kota dalam kromosom rute jika bilangan random yang dihasilkan melampaui nilai laju mutasi. Bagian 7 menandakan pemilihan rute-rute dari populasi induk yang diterapkan operasi crossover. Di mana yang dikeluarkan adalah rute yang memiliki jarak tempuh paling singkat (highest fitness).
Jika Anda melakukan tes pada source code yang diberikan tersebut, maka akan didapati bahwa nilai optimal itu bergantung pada pemilihan populasi awal. Jadi pendekatan algoritma genetik sama sekali tidak mencari mana solusi eksak (urutan kota dalam rute yang menghasilkan nilai jarak tempuh paling singkat), akan tetapi hanya mencari solusi yang sekedar bisa mereduksi jarak tempuh.
Friday, December 12, 2014
Asistensi TA dengan git version control (serta latex)
Biasanya sebagai mahasiswa semester terkahir, kita pasti dihadapkan pada kewajiban penyusunan laporan tugas akhir berupa skripsi atau tesis. Di mana dalam penyusunan laporan ini tidak serta merta apa yang kita susun tersebut langsung bisa di-approve oleh dosen pembimbing dalam sekali asistensi. Dengan demikian mau tidak mau kita harus mengeditnya berulang-ulang. Saya sebagai seorang saintis yang jam terbangnya banyak bergelut dengan studi ilmu komputer serta komputasi (walaupun masih dalam tahap amatir) punya cara tersendiri untuk mengakali situasi ini. Cara yang saya pakai tentu sudah sangat lumrah dijumpai pada bidang ini. Namun bagi Anda yang mungkin juga memiliki minat yang tinggi dalam mempelajari apapun, maka saya rasa ini sama sekali bukan hal yang terlalu ribet untuk dicoba.
Teknik yang saya maksud adalah teknik version control dengan menggunakan software git (tersedia untuk windows) serta editor latex (juga tersedia untuk windows). Soal latex sendiri, kebetulan saya ini seorang fisikawan, maka apa yang saya tulis biasanya banyak mengenai penurunan persamaan. Saya punya contoh dokument yang bisa di-download mengenai contoh kasus di mana latex itu “the only way” untuk menulis dokument, yakni
https://drive.google.com/file/d/0B1irLqfPwjq0V0VoQllWR3FTUkE/view?usp=sharing
Jika Anda bisa menghasilkan dokument yang sama (beserta nomor persamaannya di Microsoft Word atau yang lain) saya akan isikan pulsa 20 ribu. Tapi dalam tulisan ini saya tidak lagi mengajak Anda untuk memakai latex, itu pilihan Anda sepenuhnya. Dan nyatanya git ini bisa juga digunakan pada semua jenis file. Dalam tulisan ini saya lebih menekankan penggunaan teknik version control. Di wikipedia sudah diberikan secara gamblang apa yang dimaksud dengan version control. Intinya dengan menggunakan version control itu kita bisa melacak history (baca:riwayat) dari dokument.
Contoh kasus: saya sudah menyelesaikan TA, dan akan melakukan asistensi pertama kali kepada dosen pembimbing. Oleh dosen pembimbing, dalam asistensi pertama itu saya disuruhnya untuk menambahkan ini itu. Kemudian saya tambahkan lah apa yang diperintahkan, dan kemudian saya asistensi lagi untuk kedua kalinya. Pada asistensi kedua, ternyata si dosen mood nya berubah. Dia ingin agar isi laporan TA kita dirubah kembali ke situasi pertama tadi. Jadinya kita bingung. Maunya sih di-undo (pasangannya redo), tapi kan fasilitas ini hanya berlaku ketika komputer masih nyala, ketika komputer udah mati keadaan yang mau di undo tersebut sudah hilang. Bisa juga sih kita membuat satu folder untuk satu kali asistensi (jadi untuk asistensi 1 foldernya lain, untuk asistensi 2 foldernya lain, dst). Namun ini bukan cara yang efisien. Bagaimana kalo dokument kita itu saling bergantung dengan beberapa file yang lain dan ukurannya besar, misalnya file gambar. Otomatis file-file tersebut juga kita copy-paste semuanya ke dalam folder yang baru (untuk asistensi 2, 3, dst). Dan untuk navigasi dari folder 1, folder 2, dll itu juga cukup merepotkan.
Jadi untuk mengatasi masalah tersebut digunakanlah git sebagai version control. Dengan version control kita tidak melakukan teknik copy-paste file, akan tetapi yang di-lacak adalah perubahan dalam file tersebut. Jadi, alih-alih mengcopy-paste seluruh file word untuk asistensi kedua, git hanya mengcopy-paste kalimat yang kita tambahkan ke dalam file word tersebut (kata kasarnya seperti itu, walaupun implementasinya bukan seperti itu).
Untuk mempelajari git, saya g membahas di tulisan ini, ada banyak contohnya di internet (tujuan dari tulisan ini lebih kepada meningkatkan rating blog ini sekaligus memberikan sedikit pencerahan kepada Anda). Saya punya sebuah buku yang bisa Anda download di internet yang jika Anda punya waktu 5 jam sehari selama seminggu (jika memang Anda tertarik membacanya), maka Anda bisa memahami git itu apaan:
http://en.bookfi.org/book/1046931
(saya juga g sampe selesai membaca buku itu)
Adapun untuk artikel yang lebih simple dan langsung ke inti permasalahan, bisa Anda baca di sini:
http://git-scm.com/book/en/v2/Getting-Started-Git-Basics
Sementara jika Anda ingin menjadi ahli dalam git, maka ada banyak forum di internet yang membahas mengenai masalah-masalah yang dijumpai dalam menggunakan git, salah satunya di stack-overflow:
http://stackoverflow.com/questions/tagged/git?sort=newest&pageSize=15