/* 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(); } }