我的 Java 遗传算法实施似乎以中等适应值而不是高值为中心
My Java Genetic Algorithm implementation seems to center around a mid-tier fitness value instead of a high value
我的遗传算法实现了一个名为 class 的基因,它存储一个 100(trigit?)三进制字符串(最初是二进制的,但尝试过三进制)。我提供了一种评估基因适应性的方法(所有数字的总和,因此 222...222 是最佳的)。我最初的适应度等于基因与给定序列的匹配程度,但我改变了它。我还提供了一个"mutate"基因的方法。以一定的概率,基因中的每个条目都可以突变为 3 个可能的密码子之一。
我从初始人口开始。我找到最适者,杀死其他的,复制最适者("perfect"有丝分裂,突变只在下一步发生),然后突变所有基因。我 运行 这对许多 "epochs"。
最大适应度为 200,但我的算法似乎以 90-110 为中心作为每个时期的最高适应度。如果我随机生成起始基因,我的最高适应度在 120 左右,但它会很快回落到 90-110(在 1-2 个时期内)。其他 GA 实现没有这个问题。我究竟做错了什么? Java源码贴在最下面
import java.util.Random;
public class Gene {
int[] gene=new int[100];
public Gene() {
Random rand=new Random();
for(int i=0; i<100; i++){
gene[i]=rand.nextInt(3);
}
}
public int fitness(){
int sum=0;
for(int i=0; i<gene.length; i++){
sum=sum+gene[i];
}
return sum;
}
public void mutate(){
Random randP=new Random();
Random randM=new Random();
for(int i=0; i<gene.length; i++){
if(randP.nextInt(1000)<1){gene[i]=randM.nextInt(3);}
}
}
public int compareTo(Gene g){
return this.fitness()-g.fitness();
}
public String toString(){
return ""+this.fitness();
}
public void minFit(){
for(int i=0; i<gene.length; i++){
gene[i]=0;
}
}
public void maxFit(){
for(int i=0; i<gene.length; i++){
gene[i]=2;
}
}
}
public class Biome {
public static void main(String[] args) {
Gene[] species=new Gene[1000];
for(int i=0; i<1000; i++){
species[i]=new Gene();
species[i].maxFit();
}
int epoch=0;
System.out.println("start");
while(epoch<1000){
System.out.println(fittestGene(species));
sort(species);
for(int i=0; i<999; i++){species[i]=species[999];}
for(int i=0; i<1000; i++){species[i].mutate();}
epoch++;
}
}
public static Gene fittestGene(Gene[] g){
int maxIndex=0;
for(int i=0; i<g.length; i++){
if(g[i].fitness()>g[maxIndex].fitness()){maxIndex=i;}
}
return g[maxIndex];
}
public static void swap(Gene[] g, int a, int b){
Gene temp=g[a];
g[a]=g[b];
g[b]=temp;
}
public static void sort(Gene[] g){
for(int i=0; i<g.length; i++){
int minIndex=i;
for(int j=i+1; j<g.length; j++){
if(g[j].compareTo(g[minIndex])>0){swap(g, j, minIndex);}
}
}
}
}
这似乎是错误所在:
for(int i=0; i<999; i++){species[i]=species[999];}
该数组包含对 Gene
个对象的引用。因此,在该行之后,数组中的所有引用都指向同一个 Gene
对象。
你只有 1 个Gene
,它的适应度值将由均匀分布在 0 和 2 之间的 100 个整数的总和组成。这就是 90-110 值的来源。
要正确复制基因,您需要为 Gene
定义一个复制构造函数并使用它:
public class Gene {
...
public Gene(Gene other) {
this.gene = Arrays.copyOf(other.gene, other.gene.length);
}
}
然后将原行改为:
for(int i=0; i<999; i++){species[i]=new Gene(species[999]);}
我的遗传算法实现了一个名为 class 的基因,它存储一个 100(trigit?)三进制字符串(最初是二进制的,但尝试过三进制)。我提供了一种评估基因适应性的方法(所有数字的总和,因此 222...222 是最佳的)。我最初的适应度等于基因与给定序列的匹配程度,但我改变了它。我还提供了一个"mutate"基因的方法。以一定的概率,基因中的每个条目都可以突变为 3 个可能的密码子之一。
我从初始人口开始。我找到最适者,杀死其他的,复制最适者("perfect"有丝分裂,突变只在下一步发生),然后突变所有基因。我 运行 这对许多 "epochs"。
最大适应度为 200,但我的算法似乎以 90-110 为中心作为每个时期的最高适应度。如果我随机生成起始基因,我的最高适应度在 120 左右,但它会很快回落到 90-110(在 1-2 个时期内)。其他 GA 实现没有这个问题。我究竟做错了什么? Java源码贴在最下面
import java.util.Random;
public class Gene {
int[] gene=new int[100];
public Gene() {
Random rand=new Random();
for(int i=0; i<100; i++){
gene[i]=rand.nextInt(3);
}
}
public int fitness(){
int sum=0;
for(int i=0; i<gene.length; i++){
sum=sum+gene[i];
}
return sum;
}
public void mutate(){
Random randP=new Random();
Random randM=new Random();
for(int i=0; i<gene.length; i++){
if(randP.nextInt(1000)<1){gene[i]=randM.nextInt(3);}
}
}
public int compareTo(Gene g){
return this.fitness()-g.fitness();
}
public String toString(){
return ""+this.fitness();
}
public void minFit(){
for(int i=0; i<gene.length; i++){
gene[i]=0;
}
}
public void maxFit(){
for(int i=0; i<gene.length; i++){
gene[i]=2;
}
}
}
public class Biome {
public static void main(String[] args) {
Gene[] species=new Gene[1000];
for(int i=0; i<1000; i++){
species[i]=new Gene();
species[i].maxFit();
}
int epoch=0;
System.out.println("start");
while(epoch<1000){
System.out.println(fittestGene(species));
sort(species);
for(int i=0; i<999; i++){species[i]=species[999];}
for(int i=0; i<1000; i++){species[i].mutate();}
epoch++;
}
}
public static Gene fittestGene(Gene[] g){
int maxIndex=0;
for(int i=0; i<g.length; i++){
if(g[i].fitness()>g[maxIndex].fitness()){maxIndex=i;}
}
return g[maxIndex];
}
public static void swap(Gene[] g, int a, int b){
Gene temp=g[a];
g[a]=g[b];
g[b]=temp;
}
public static void sort(Gene[] g){
for(int i=0; i<g.length; i++){
int minIndex=i;
for(int j=i+1; j<g.length; j++){
if(g[j].compareTo(g[minIndex])>0){swap(g, j, minIndex);}
}
}
}
}
这似乎是错误所在:
for(int i=0; i<999; i++){species[i]=species[999];}
该数组包含对 Gene
个对象的引用。因此,在该行之后,数组中的所有引用都指向同一个 Gene
对象。
你只有 1 个Gene
,它的适应度值将由均匀分布在 0 和 2 之间的 100 个整数的总和组成。这就是 90-110 值的来源。
要正确复制基因,您需要为 Gene
定义一个复制构造函数并使用它:
public class Gene {
...
public Gene(Gene other) {
this.gene = Arrays.copyOf(other.gene, other.gene.length);
}
}
然后将原行改为:
for(int i=0; i<999; i++){species[i]=new Gene(species[999]);}