初学遗传算法,一个练手的小程序

原创 2008年10月03日 20:32:00
    最近研究了一下遗传算法,挺有意思的,在一个老外的网站上看到了这个小例子,比较有趣,自己用java实现了一下(老外是用c++实现的)。
    问题:有10张纸牌,编号分别是1到10,现在要将这10张纸牌分为2堆,其中一堆求和为36,另一堆求积为360,问应该怎么分?(也就是说,最终的结果应该是:一堆为2+7+8+9+10=36,另一堆为1*3*4*5*6=360。当然,如果修改题目中的参数,改为32和360,那么结果就是2+3+4+6+7+10=32 和 1*5*8*9=360)
原文地址:http://www.codeproject.com/KB/recipes/Genetic_Algorithm.aspx
另外,这个算法不保证每次都有结果,一般多运行几次是会得到结果的,当然,如果本身无解,那自然是永远也找不到结果的。

  1. package andycpp;
  2. import java.util.Random;
  3. public class CardGA {
  4.     /**
  5.      * @param args
  6.      */
  7.     public static void main(String[] args) {
  8.         new CardGA().run();
  9.     }
  10.     private final int pop_size = 30;        //人口池容量
  11.     private final int chrom_length = 10;    //染色体长度
  12.     private final float crossover_rate = 0.6f;  //杂交率
  13.     private final float mutation_rate = 0.01f;  //变异率
  14.     private final int max_generation = 1000;    //繁殖次数的上限
  15.     private final int sum_tagart = 32;          //纸牌求和的目标值
  16.     private final int product_targart = 360;    //纸牌求积的目标值
  17.     private static Random rand = new Random();  //随机数产生器
  18.     
  19.     private int[][] population = new int[pop_size][chrom_length];   //人口池
  20.     
  21.     public void run() {
  22.         int generation = 0;
  23.         initPopuation(population);
  24.         int winner = 0, loser = 0;
  25.         while(generation < max_generation) {
  26.             generation++;
  27.             winner = rand.nextInt(pop_size);
  28.             loser = rand.nextInt(pop_size);
  29.             if(getFitness(winner) > getFitness(loser)) {
  30.                 int temp = winner;
  31.                 winner = loser;
  32.                 loser = temp;
  33.             }
  34.             if(isAnswer(winner))
  35.                 break;
  36.             crossover(winner, loser);
  37.             mutation(loser);
  38.             if(isAnswer(loser)) {
  39.                 winner = loser;
  40.                 break;
  41.             }
  42.         }
  43.         if(generation == max_generation)
  44.             System.out.println("没找到合适的结果");
  45.         else
  46.             System.out.println("在第"+generation+"代"+parseToString(winner));
  47.     }
  48.     /**
  49.      * 将某个染色体解析为内容友好的字符串
  50.      */
  51.     private String parseToString(int chrom) {
  52.         StringBuilder result = new StringBuilder();
  53.         StringBuilder sum = new StringBuilder();
  54.         StringBuilder prod = new StringBuilder();
  55.         for(int i=0; i<chrom_length; i++) {
  56.             if(population[chrom][i] == 0)
  57.                 sum.append((i+1) + "+");
  58.             else
  59.                 prod.append((i+1) + "*");
  60.         }
  61.         sum.replace(sum.length()-1, sum.length(), "="+sum_tagart);
  62.         prod.replace(prod.length()-1, prod.length(), "="+product_targart);
  63.         result.append("找到了合适的纸牌组合,分别是:" + System.getProperty("line.separator"));
  64.         result.append(sum.toString() + System.getProperty("line.separator"));
  65.         result.append(prod.toString() + System.getProperty("line.separator"));
  66.         
  67.         return result.toString();
  68.     }
  69.     /**
  70.      * 判断某个染色体是否就是最终答案
  71.      */
  72.     private boolean isAnswer(int chrom) {
  73.         if(getFitness(chrom) == 0f) {
  74.             return true;
  75.         }
  76.         return false;
  77.     }
  78.     /**
  79.      * 对染色体进行变异
  80.      */
  81.     private void mutation(int chrom) {
  82.         for(int i=0; i<chrom_length; i++) {
  83.             if(rand.nextFloat()<mutation_rate) {
  84.                 population[chrom][i] = (population[chrom][i]+1)%2;
  85.             }
  86.         }
  87.     }
  88.     /**
  89.      * 将两个染色体进行杂交,winner不变,只修改loser
  90.      */
  91.     private void crossover(int winner, int loser) {
  92.         for(int i=0; i<chrom_length; i++) {
  93.             if(rand.nextFloat()<crossover_rate)
  94.                 population[loser][i] = population[winner][i];
  95.         }
  96.     }
  97.     /**
  98.      * 取得第i个染色体的符合度,符合度越小越好
  99.      */
  100.     private float getFitness(int chrom) {
  101.         int sum = 0;
  102.         int prod = 1;
  103.         for(int i=0; i<chrom_length; i++) {
  104.             if(population[chrom][i]==0)
  105.                 sum += (1+i);
  106.             else
  107.                 prod *= (1+i);
  108.         }
  109.         return (float)Math.abs(sum - sum_tagart)/sum_tagart + (float)Math.abs(prod - product_targart)/product_targart;
  110.     }
  111.     /**
  112.      * 初始化人口池,数组的内容为0或者1,
  113.      * 0标识该扑克牌被分配到求和组
  114.      * 1标识该扑克牌被分配到求积组
  115.      */
  116.     private void initPopuation(int[][] population2) {
  117.         for(int i=0; i<pop_size; i++)
  118.             for(int j=0; j<chrom_length; j++) {
  119.                 if(rand.nextFloat()<0.5f)
  120.                     population[i][j] = 0;
  121.                 else
  122.                     population[i][j] = 1;
  123.             }
  124.         
  125.     }
  126. }

一个遗传算法的Java小程序

  • 2011年12月02日 13:42
  • 33KB
  • 下载

Python3 统计代码 - 练手小程序(一)

计算代码行数,看看自己项目的规模,不知道自己项目的规模,怎么好吹牛逼呢?说起来,我也是维护过三百万代码量的项目的人。(我吹个牛逼,应该不至于骂我吧)你知我长短,我知你深浅,知己知彼,知己知彼啊。...
  • CSND_Ayo
  • CSND_Ayo
  • 2017年05月03日 21:07
  • 1570

有了这个列表,程序员不愁没练手的小项目了

翻译原文地址:http://blog.jobbole.com/49762/ 英文原文地址:http://www.dreamincode.net/forums/topic/78802-martyr2s...
  • awp0011
  • awp0011
  • 2015年11月09日 11:42
  • 2245

Qt:练手的小程序,分享出来

Qt:练手小程序,分享源码。
  • rl529014
  • rl529014
  • 2016年11月24日 00:22
  • 2932

简单小程序敲着练手额~

2.1 #include int main(void) {     int q;     q = 1;     printf("%d is neat.\n",q);     return 0; } ...
  • BrotherJing8023
  • BrotherJing8023
  • 2016年12月15日 00:28
  • 339

小程序练手(c++)

给定一个数组input[] ,如果数组长度n为奇数,则将数组中最大的元素放到 output[] 数组最中间的位置,如果数组长度n为偶数,则将数组中最大的元素放到 output[] 数组中间两个位置偏右...
  • u010951938
  • u010951938
  • 2014年12月08日 10:25
  • 1230

PHP学习练手(十二)

发送电子邮件 函数: 1、发送邮件函数: (subject中不能包含换行符;正文中每一行的长度都不能超过70,故用wordwrap函数进行隔断)mail(to, subject, body, [...
  • u014033518
  • u014033518
  • 2016年01月07日 20:12
  • 894

Python 练手程序合集(一)

一、百钱百鸡 公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,用100文钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100文钱。# encoding: utf-...
  • tan6600
  • tan6600
  • 2016年01月28日 16:28
  • 13157

v2ex一个简单易懂的微信小程序练手项目

由标题所示,这个v2ex小程序是我根据客户端改造而成,当然并不是完完全全地根据v2ex的客户端进行改造的,其中客户端有些功能也暂时还没有移植过来,不过作为一个练手的项目,个人觉得还是蛮不错的,不多说了...
  • u010933680
  • u010933680
  • 2017年01月14日 18:01
  • 962

mysql练手专用项目

Sutdent表的定义 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增...
  • ligou8000
  • ligou8000
  • 2015年07月03日 11:30
  • 1607
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:初学遗传算法,一个练手的小程序
举报原因:
原因补充:

(最多只允许输入30个字)