9.1 遗传算法:启发自真实现象
1.传统遗传算法:
随着猜测答案的迭代次数增加,答案可以发生进化(如二分法猜数)
2.交互式选择
用户点击过A后,程序根据A自动产生(进化出)与A相似的搜索结果
3.生态系统模拟
9.2 为什么使用遗传算法
尽管计算机对进化过程的模拟可以追溯到20世纪50年代,但大部分人认为当今的遗传算法(Genetic Algorithm,GA)是由密歇根大学的约翰·霍兰德教授率先提出的。
求解答案已知的问题有助于我们验证算法的正确性。一旦遗传算法成功地解决了这个问题,它的有效性就能得到证明。我 们就能以更自信的心态用它求解答案未知的问题。所以,第一个示例的目的仅仅在于 演示遗传算法的工作原理。如果GA算出的结果和已知结果相同,就代表它已被正确地实现。
9.4 遗传算法,第一部分:创建种群
遗传领域有两个重要概念:基因型和表现型,两者之间有重要区别。基因型 (genotype)就是遗传密码,也就是本例的字符串,它会从父代传给子代;表现型 (phenotype)就是基因型的表达。
9.5 遗传算法,第二部分:选择
1.评估适应度
为了让遗传算法有效,我们需要设计一个适应度函数。这个函数会产生一个描述个体 适应度的分值。
再一次简化这个问题,假设我们只想进化出单词“cat”,“car”有两个正确字符,它的适应度最高。“hut”只有一个正 确字符,“box”没有正确字符。
因此,适应度函数如下: 适应度 = 正确字符的数量
2.创建交配池
概率方法,我们称为“命运之轮”
假设种群中有5个个体,它们都有自己的适应度分值。
9.5 遗传算法,第三部分:繁殖
1.交叉
2.突变
突变的作用就是在进化过程中不断引入多样性。
一个遗传算法可能有5%、1%或0.1%的突变率。假设交叉完成后,某子代个体是“FORY”,如果突变率为1%,这意味着每个字符有1%的突变概 率。而字符怎么发生突变呢?
在本例中,我们把突变定义为用一个随机的字符替换原字符。
在获得新种群之前,我们会不断地进行选择(选择两个父本)和繁殖(交叉和突变) 操作。一旦子代种群代替了当前种群,我们还会回到之前的步骤:再次评估适应度, 再次进行选择和繁殖操作。
9.6 遗传算法步骤
SETUP
第1步:初始化 创建由N个个体组成的种群,随机确定个体的DNA。
LOOP
第2步:选择 评估个体的适应度,创建交配池。
第3步:繁殖 重复N次。
a) 根据相对适应度,概率性地选择两个父本。
b) 杂交——结合父本的DNA,创建出一个“子代个体”。
c) 突变——以一定的概率使子代的DNA发生突变。
d) 将这个子代加入新种群。 第4步:用新种群替换旧种群,再回到第2步。
class DNA
{
char[] genes = new char[18];
DNA()
{
for (int i = 0; i < genes.lenght; i++)
{
genes[i] = (char) random(32,128); //从编号为32~128的ASCII字符中随机选择一系列字
}
}
}
String target = "to be or not to be";
class DNA
{
float fitness; //在DNA类中加入一个适应度变量
void fitness () //该函数的作用是计算适应度
{
int score = 0;
for (int i = 0; i < genes.length; i++)
{
if (genes[i] == target.charAt(i)) //字符是否正确
{
score++; //如果正确,增加分值
}
}
fitness = float(score)/target.length(); //适应度就是正确字符的百分比
}
}
void mutate()
{
for (int i = 0; i < genes.length; i++) //遍历数组中的每个基因
{
if(random(1) < mutationRate)
{
genes[i] = (char) random(32,128); //突变,产生随机字符
}
}
}
9.8 遗传算法:整合代码
遗传算法:进化出莎士比亚名言
float mutationRate; //突变率
int totalPopulation = 150; //个体总数
DNA[] population; //个体数组
ArrayList<DNA> matingPool; //交配池数组
String target; //目标答案
void setup() {
size(200, 200);
target = "to be or not to be"; //初始化目标答案和突变率
mutationRate = 0.01;
population = new DNA[totalPopulation]; //步骤1:初始化种群
for (int i = 0; i < population.length; i++) {
//步骤2a:计算适应度
population[i] = new DNA();
}
}
void draw() {
for (int i = 0; i < population.length; i++)<