使用Java模拟达尔文进化论中物竞天择的过程:
分为三个部分:
第一步:初始化族群
第二步:选择
第三步:繁殖
结果展示:
族群类:
import java.util.ArrayList;
import java.util.Random;
/**
* @Auther: wdq
* @Date: 2021/4/18 21:11
* @Description:
*/
public class Population {
/**
* 突变率
*/
private static float mutationRate;
/**
* 个体数组
*/
private static DNA[] populations;
/**
* 目标答案
*/
private static String target;
/**
* 代数
*/
private static int cnt = 0;
/**
* 输出适应度最好的一个
*
* @param cnt 代数
*/
private static void printBest(int cnt) {
float t = 0;
int index = 0;
for (int i = 0; i < populations.length; i++) {
if (t < populations[i].fitness) {
t = populations[i].fitness;
index = i;
}
}
System.out.println("第" + cnt + "代中,适应度" + (int) (populations[index].fitness * 100) + "%:" + populations[index].getPhrase());
}
/**
* 选择
*/
private static void draw() {
// 计算适应度
for (DNA population : populations) {
population.fitness(target);
}
printBest(cnt);
// 创建交配池
ArrayList<DNA> matingPool = new ArrayList<>();
// 按照适应度得分将个体加入交配池
for (DNA population : populations) {
int n = (int) (population.fitness * 100);
for (int j = 0; j <= n; j++) {
matingPool.add(population);
}
}
// 繁殖
Random random = new Random();
for (int i = 0; i < populations.length; i++) {
int a = random.nextInt(matingPool.size());
int b = random.nextInt(matingPool.size());
DNA parentA = matingPool.get(a);
DNA parentB = matingPool.get(b);
// 交叉
DNA child = parentA.crossover(parentB);
// 变异
child.mutate(mutationRate);
populations[i] = child;
}
}
/**
* 初始化
*/
private static void setup() {
int totalPopulation = 150;
target = "tobeornottobe";
mutationRate = (float) 0.01;
populations = new DNA[totalPopulation];
for (int i = 0; i < populations.length; i++) {
populations[i] = new DNA(target.length());
}
}
/**
* 主程序
* @param args
*/
public static void main(String[] args) {
setup();
boolean ok = true;
while (ok) {
cnt++;
draw();
for (DNA population : populations) {
if (population.getPhrase().equals(target)) {
ok = false;
population.fitness(target);
System.out.println("第"+(cnt+1)+"代中,适应度"+(int)(population.fitness*100)+"%:"+population.getPhrase());
break;
}
}
}
}
}
DNA类
import java.util.Random;
/**
* @Auther: wdq
* @Date: 2021/4/18 20:51
* @Description:
*/
public class DNA {
public char[] genes;
public float fitness;
/**
* 构造函数
*
* @param num DNA长度
*/
public DNA(int num) {
Random random = new Random();
genes = new char[num];
for (int i = 0; i < genes.length; i++) {
genes[i] = (char) (random.nextInt(128 - 32) + 32);
}
}
/**
* 计算适应度
*
* @param target 目标
*/
public void fitness(String target) {
int score = 0;
for (int i = 0; i < genes.length; i++) {
if(genes[0] == 't')
{
int a=0;
}
if (genes[i] == target.charAt(i)) {
score ++;
}
}
fitness = (float) score / (float)target.length();
}
/**
* 繁殖
* @param partner 和该DNA结合的DNA
* @return DNA
*/
public DNA crossover(DNA partner) {
DNA child = new DNA(genes.length);
int midpoint = new Random().nextInt(genes.length);
for (int i = 0; i < genes.length; i++) {
if (i < midpoint) child.genes[i] = genes[i];
else child.genes[i] = partner.genes[i];
}
return child;
}
/**
* 突变
*
* @param mutationRate 突变概率
*/
public void mutate(float mutationRate) {
Random random = new Random();
for (int i = 0; i < genes.length; i++) {
if (Math.random() < mutationRate) {
genes[i] = (char) (random.nextInt(128 - 32) + 32);
}
}
}
/**
* 转换成字符串
* @return 表现型
*/
public String getPhrase() {
return new String(genes);
}
}
创建自己的遗传算法
1、更改变量
突变因子和族群数量可修改
2、适应度函数
适应度函数设计的好坏影响算法本身
3、基因型和表现型
表现型包含基因型。dna的基因不同,表现型可能相同也可能不同。设计类的时候,基因型可以设计成表现型的内部类
参考文献:《代码本色 用编程模拟自然系统》