/*
GASample - Sample of Genetic Algorithm
Copyright (C) 2004 youjin lee(justbear@naver.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
/**
* Organism(»ý¹°Ã¼) Ŭ·¡½º´Â °³°³ÀÇ »ý¹° °³Ã¼¸¦ ³ªÅ¸³À´Ï´Ù.
* °¢ »ý¹°Ã¼´Â ¿°»öü(chromosome)¸¦ °¡Áö°í ÀÖÀ¸¸ç À¯ÀüÀ» ÇÒ¶§ ºÎ¸ðÀÇ ¿°»öü°¡
* ¼·Î ²¿¿©¼(crossover) »õ·Î¿î À¯ÀüÀÚ Á¤º¸¸¦ °¡Áø ÀÚ½ÄÀ» ¸¸µé¾î ³À´Ï´Ù.
* @author justbear
*/
class Organism {
/**
* »ý¹°Ã¼ÀÇ ¿°»öü(chromosome)¸¦ ³ªÅ¸³»¸ç, À¯ÀüÀÚ ¾Ë°í¸®Áò(Genetic Algorithm)¿¡ »ç¿ëÇÒ
* ÆÄ¶ó¹ÌÅÍ ¹è¿·Î »ç¿ëÇÕ´Ï´Ù.
* int ŸÀÔÀ¸·Î °íÁ¤ÇÕ´Ï´Ù.
*/
int[] chromosome;
/**
* fitness °ªÀ» ÀúÀåÇϴµ¥ »ç¿ëÇÕ´Ï´Ù. fitness¶õ ±¸ÇϰíÀÚ ÇÏ´Â ÇØ´ä°ú ¾ó¸¶³ª ÀûÁ¤ÇѰ¡¸¦
* ³ªÅ¸³»´Â ÁöÇ¥·Î ¿©±â ¿¹¿¡¼´Â ¼ýÀÚ°¡ 0¿¡ °¡±î¿ï¼ö·Ï ÇØ´ä°ú °¡±î¿î °ªÀÌ µË´Ï´Ù.
*/
int fitness;
/**
* »ý¼ºÀڷνá GASample.CHROMOSOME_SIZE °³¼ö¸¸Å int ¹è¿À» »ý¼ºÇÕ´Ï´Ù.
* CHROMOSOME_SIZE¶õ °³°³ÀÇ »ý¹°Ã¼°¡ °¡Áö´Â ¿°»öüÀÇ °³¼ö¸¦ ³ªÅ¸³À´Ï´Ù.
*/
public Organism() {
chromosome = new int[GASample.CHROMOSOME_SIZE];
}
}
/**
* OrganismComparator Ŭ·¡½º´Â Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ)À» Á¤·ÄÇÒ¶§
* »ç¿ëÇÕ´Ï´Ù. ComparatorÀÇ »ç¿ë¹ýÀº JDK API ¹®¼¸¦ ÂüÁ¶Çϼ¼¿ä.
* @author justbear
*/
class OrganismComparator implements Comparator {
public int compare(Object o1, Object o2) {
Organism c1 = (Organism) o1;
Organism c2 = (Organism) o2;
return c1.fitness - c2.fitness;
}
}
/**
* ÀÌ ¿¹Á¦´Â À¯ÀüÀÚ ¾Ë°í¸®ÁòÀ¸·Î ¹æÁ¤½ÄÀÇ Àμö °ªÀ» ±¸ÇÏ´Â ¹æ¹ýÀ» º¸¿©ÁÝ´Ï´Ù.
* ¹æÁ¤½ÄÀº a+2b+3c+4d+5e=100 À¸·Î ÀÌ ½Ä¿¡ Àû´çÇÑ a, b, c, d, e °ªÀ» ±¸ÇÕ´Ï´Ù.
* ÀÌ ½ÄÀº calculateFitness() ¸Þ¼Òµå¿¡¼ º¸½Ç ¼ö ÀÖ½À´Ï´Ù.
* @author justbear
*/
public class GASample {
/**
* À¯ÀüÀÚ ¾Ë°í¸®Áò¿¡ »ç¿ëÇÒ OrganismÀÇ Àüü °³¼ö
*/
private int POPULATIONS_SIZE = 2048;
/**
* À¯ÀüÀÚ ¾Ë°í¸®Áò¿¡¼´Â »õ·Î¿î ¼¼´ë(Generation)°¡ ³ªÅ¸³¯ ¶§¸¶´Ù ¶Ù¾î³ ÇüÁúÀ» °¡Áø
* »ý¹°Ã¼´Â °è¼Ó »ýÁ¸ÇÏ¿© ±× ÇüÁúÀ» ÀÚ¼Õ¿¡¼ À¯Àü½ÃŰ°Ô µË´Ï´Ù. ELITISM_SIZE´Â Àüü
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ ÀÚ½ÅÀÇ ÇüÁúÀ» °è¼Ó À¯ÀüÇÒ °´Ã¼ÀÇ °³¼ö¸¦
* ³ªÅ¸³À´Ï´Ù. Áï, Àüü »ý¹°Ã¼ Áß ELITISM_SIZE °³¼ö¸¸ÅÀÇ ¶Ù¾î³ »ý¹°Ã¼´Â ±× À¯ÀüÀÚ
* Á¤º¸¸¦ º¯È½ÃŰÁö ¾ÊÀº ºÎ¸ð ±×´ë·ÎÀÇ ÀÚ½ÄÀ» »ý¼ºÇÕ´Ï´Ù.
*/
private int ELITISM_SIZE = 100;
/**
* ÇÑ ¿°»öü(chromosome)°¡ °¡Áö´Â ÃÖ´ë°ª
*/
private int MAX_CHROMOSOME_DATA = 100;
/**
* »ý¹°Ã¼(Organism)°¡ °¡Áö´Â ¿°»öü(chromosome)ÀÇ °³¼ö
*/
public static int CHROMOSOME_SIZE = 5;
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ)À» ³ªÅ¸³»´Â º¯¼ö
*/
private LinkedList populations;
/**
* À¯ÀüÀÚ ¾Ë°í¸®Áò °è»ê¿¡¼ »ç¿ëÇÏ´Â Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) º¯¼öÀÇ ¹öÆÛ
*/
private LinkedList buffer;
/**
* GASample »ý¼ºÀÚ
*/
public GASample() {
doGA();
}
/**
* À¯ÀüÀÚ ¾Ë°í¸®ÁòÀ» ½ÇÇà
*/
public void doGA() {
initPopulations();
// ³¡³ª´Â Á¶°ÇÀÌ ¸ÂÀ» ¶§±îÁö ¹Ýº¹ÇÕ´Ï´Ù.
while (true) {
evaluate();
sortPopulations();
printOrganism(0);
checkFinish();
elitism();
crossover();
mutate();
swap();
}
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ)À» ÃʱâÈÇÔ
*/
public void initPopulations() {
populations = new LinkedList();
buffer = new LinkedList();
for (int i = 0; i < POPULATIONS_SIZE; i++) {
populations.add(initOrganism());
}
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ)ÀÇ °¢ »ý¹°Ã¼ÀÇ fitness °ªÀ» ¼³Á¤ÇÕ´Ï´Ù.
*/
public void evaluate() {
for (int i = 0; i < POPULATIONS_SIZE; i++) {
Organism c = (Organism) populations.get(i);
c.fitness = calculateFitness(c.chromosome);
}
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ)ÀÇ °¢ »ý¹°Ã¼(Organism)¸¦ fitness°¡ ³·Àº ¼øÀ¸·Î
* Á¤·ÄÇÕ´Ï´Ù. fitness °ªÀÌ ³·À» ¼ö·Ï ´õ ¶Ù¾î³, Áï ã°íÀÚ ÇÏ´Â ÇØ´ä°ú À¯»çÇÑ
* »ý¹°Ã¼(Organism) ÀÔ´Ï´Ù.
*/
public void sortPopulations() {
// ¸Å¹ø Á¤·ÄÀ» ÇÒ¶§¸¶´Ù OrganismComparator °´Ã¼¸¦ »ý¼ºÇÏ´Â °ÍÀº ÁÁÁö ¾Ê½À´Ï´Ù.
// óÀ½¿¡ Çϳª »ý¼ºÇؼ °è¼Ó »ç¿ëÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. ¼³¸íÀ» À§ÇÏ¿© °£´ÜÈ÷ ÇÕ´Ï´Ù.
Collections.sort(populations, new OrganismComparator());
}
/**
* ¹Ýº¹À» Áß´ÜÇÏ´ÂÁö¸¦ È®ÀÎÇÕ´Ï´Ù. ¹Ýº¹À» Áß´ÜÇÏ´Â °ÍÀº À¯ÀüÀÚ ¾Ë°í¸®Áò¿¡¼ ´õÀÌ»ó »õ·Î¿î
* ¼¼´ë(Generation)¸¦ »ý¼ºÇÏÁö ¾Ê´Â °ÍÀ» ÀǹÌÇÕ´Ï´Ù. ù¹øÂ° »ý¹°Ã¼(Organism)ÀÇ fitness °ªÀÌ
* 0ÀÎ °æ¿ì ÇÁ·Î±×·¥À» Áß´ÜÇÕ´Ï´Ù.
*/
public void checkFinish() {
Organism c = (Organism) populations.get(0);
if (c.fitness == 0)
System.exit(0);
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ ¶Ù¾î³ À¯ÀüÀÚ¸¦ Áö´Ñ »ý¹°Ã¼(Organism)¸¦
* ELITISM_SIZE °³¼ö¸¸Å Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) ¹öÆÛ¿¡ ÀúÀåÇÕ´Ï´Ù.
*/
public void elitism() {
for (int i = 0; i < ELITISM_SIZE; i++) {
Organism c = new Organism();
c.chromosome = ((Organism) populations.get(i)).chromosome;
c.fitness = ((Organism) populations.get(i)).fitness;
buffer.add(c);
}
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ ÀÓÀÇÀÇ µÎ »ý¹°Ã¼(Organism)¸¦ ±³¹è(crossover)½ÃÄÑ
* »õ·Î¿î ÀÚ½Ä »ý¹°Ã¼(Organism)¸¦ ¸¸µé°í Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) ¹öÆÛ¿¡ ÀúÀåÇÕ´Ï´Ù.
*/
public void crossover() {
for (int i = 0; i < POPULATIONS_SIZE - ELITISM_SIZE; i++) {
// getRandomPopulation()ÀÇ °ªÀÌ ¶È°°ÀºÁö È®ÀÎÇÏ´Â ÀÛ¾÷ÀÌ ÇÊ¿äÇÕ´Ï´Ù.
// °£´ÜÈ÷ Çϱâ À§ÇÏ¿© ±× °úÁ¤À» »ý·«ÇÕ´Ï´Ù.
Organism c1 = (Organism) populations.get(getRandomPopulation());
Organism c2 = (Organism) populations.get(getRandomPopulation());
// getRandomPositionOfPopulation()ÀÇ °ªÀÌ 0ÀÎÁö È®ÀÎÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù.
// °£´ÜÈ÷ Çϱâ À§ÇÏ¿© ±× °úÁ¤À» »ý·«ÇÕ´Ï´Ù.
int position = getRandomChromosomePosition();
Organism c = new Organism();
System.arraycopy(c1.chromosome, 0, c.chromosome, 0, position);
System.arraycopy(c2.chromosome, 0, c.chromosome, position, CHROMOSOME_SIZE
- position);
buffer.add(c);
}
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ ÀÓÀÇÀÇ ÇÑ »ý¹°Ã¼¸¦ µ¹¿¬º¯ÀÌ(mutate) ½Ãŵ´Ï´Ù.
* µ¹¿¬º¯ÀÌ(mutate)¸¦ ½ÃŰ´Â ÀÌÀ¯´Â ±³¹è(crossover)¸¸ ½ÃŰ´Â °æ¿ìº¸´Ù ´õ randomÇÑ °ªÀ»
* »ý¼ºÇÏ¿© ¾Ë°í¸®ÁòÀÇ È¿À²À» ³ôÀ̱â À§ÇؼÀÔ´Ï´Ù.
*/
public void mutate() {
Organism c = (Organism) buffer.get(getRandomPopulation());
int position = getRandomChromosomePosition();
c.chromosome[position] = (int) (Math.random() + MAX_CHROMOSOME_DATA);
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) ¹öÆÛÀÇ °ªÀ» ¿ø·¡ Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) º¯¼ö¿¡
* º¹»çÇÕ´Ï´Ù. Áï »õ·Î¿î ¼¼´ë(New Generation)¸¦ ¸¸µì´Ï´Ù.
*/
public void swap() {
for (int i = 0; i < POPULATIONS_SIZE; i++) {
populations.remove(0);
}
for (int i = 0; i < POPULATIONS_SIZE; i++) {
populations.add(buffer.remove(0));
}
}
/**
* ÃʱâÈµÈ Organism °´Ã¼¸¦ ¹ÝȯÇÕ´Ï´Ù. OrganismÀÇ chromosome º¯¼ö ¹è¿µéÀÇ ÃʱⰪÀº
* MAX_CHROMOSOME_DATA °ªÀ» ÃʰúÇÏÁö ¾Ê½À´Ï´Ù.
*
* @return ÃʱâÈµÈ Organism °´Ã¼
*/
public Organism initOrganism() {
Organism c = new Organism();
for (int i = 0; i < CHROMOSOME_SIZE; i++)
c.chromosome[i] = (int) (Math.random() * MAX_CHROMOSOME_DATA);
return c;
}
/**
* ÇÑ »ý¹°Ã¼(Organism)ÀÇ ¿°»öü(Chromosome) Áß¿¡¼ ÀÓÀÇÀÇ À§Ä¡¸¦ ¹ÝȯÇÕ´Ï´Ù.
* @return ¿°»öü(Chromosome) Áß ÀÓÀÇÀÇ À§Ä¡
*/
public int getRandomChromosomePosition() {
return (int) (Math.random() * CHROMOSOME_SIZE);
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ ÀÓÀÇÀÇ »ý¹°Ã¼(Organism)ÀÇ À§Ä¡¸¦ ¹ÝȯÇÕ´Ï´Ù.
* @return Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ ÀÓÀÇÀÇ »ý¹°Ã¼(Organism)ÀÇ À§Ä¡
*/
public int getRandomPopulation() {
return (int) (Math.random() * POPULATIONS_SIZE);
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) ÁßÀÇ °¢°¢ÀÇ »ý¹°Ã¼(Organism)¿¡ ´ëÇÏ¿© fitness °ªÀ»
* °è»êÇÕ´Ï´Ù. fitness °ªÀº Àý´ë°ªÀ¸·Î ³ªÅ¸³À´Ï´Ù.
* @return fitness °ª
*/
public int calculateFitness(int[] values) {
return Math.abs(values[0] + 2 * values[1] + 3 * values[2] + 4
* values[3] + 5 * values[4] - 100);
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ ÀԷ¹ÞÀº À§Ä¡ÀÇ »ý¹°Ã¼(Organism)ÀÇ °ªÀ»
* Ãâ·ÂÇÕ´Ï´Ù. »ý¹°Ã¼(Organism)ÀÇ ¿°»öü(chromosome) ¹è¿À» Áß°£¿¡ ½ºÆäÀ̽º¸¦ µÎ¾î
* Ãâ·ÂÇϰí, '['¿Í ']' »çÀÌ¿¡ fitness °ªÀ» Ãâ·ÂÇÕ´Ï´Ù.
* @param Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ) Áß¿¡¼ Ãâ·ÂÇÒ »ý¹°Ã¼(Organism)ÀÇ À§Ä¡
*/
public void printOrganism(int row) {
Organism c = (Organism) populations.get(row);
for (int i = 0; i < CHROMOSOME_SIZE; i++)
System.out.print(c.chromosome[i] + " ");
System.out.println("[" + c.fitness + "]");
}
/**
* Àα¸(Population, »ý¹°Ã¼ÀÇ ¸ðÀÓ)ÀÇ Àüü »ý¹°Ã¼(Organism)ÀÇ °ªÀ» Ãâ·ÂÇÕ´Ï´Ù.
* »ý¹°Ã¼(Organism)ÀÇ ¿°»öü(chromosome) ¹è¿À» Áß°£¿¡ ½ºÆäÀ̽º¸¦ µÎ¾î Ãâ·ÂÇϰí,
* '['¿Í ']' »çÀÌ¿¡ fitness °ªÀ» Ãâ·ÂÇÕ´Ï´Ù.
*/
public void printOrganisms() {
for (int i = 0; i < POPULATIONS_SIZE; i++)
printOrganism(i);
}
/**
* ½ÇÇàÇϱâ À§ÇÑ main ¸Þ¼Òµå
*/
public static void main(String[] args) {
new GASample();
}
}