遗传算法简单案例笑脸拟合(6x6矩阵)(java)
原图是一个6x6的由0,1组成的数组按特定格式排列组成的矩阵,我们可以将其扁平化构成的1*36的一维向量作为原图染色体,进行以下步骤
(1)随机生成包含五个染色体的祖先群落
(2)随机选择两对染色体进行基因互换,通过互换生成五个新的染色体,互换原则:随机选择长度为六的连续基因序列进行基因互换。
(3)所有染色体在随机位置进行基因变异,【0,1】进行对调。
(4)把十个染色体放在一起,分别与原图求基因差值的平方和,作为本案例的适合度值并进行排序,选择值最小的五个染色体,作为优胜染色体群落,将适合度值最小的染色体逆扁平化生成矩阵输出近似图像。一次循环完成。
(5)下一次循环前,将优胜染色体群落替换祖先群落重复步骤2-5,染色体群落不断迭代,优胜劣汰逐步进化到原图状态。
本案例本质上是用数组将数组看作基因链相互交换以及突变不断迭代使结果贴近给出的数组
为了方便查看将数组以矩阵输出近似图像
笑脸图像[0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0]
初始随机图像(其一)
三十五代后
八十代后(每次运行得到结果的代数不同)
解题思路:
先准备五个亲本
进行交换生成五个子代
合并为十个,根据其与笑脸的差值平方和排序
取值小的五个进行基因突变并作为下一代亲本
持续迭代直到得出结果
类:
基因类:数组,基因交换方法,基因突变方法,计算差值平方和方法
执行类:初始化笑脸,初始化五个随机亲本,循环(直到得到结果){ 亲本基因交换生成五个子代,亲本与子代合并后排序,每代输出差值最小的一个,差值小的五个进行基因突变作为下一代亲本 }
基因类:
package genepack;
import java.util.ArrayList;
import java.util.List;
public class gene {//基因类一个数组用于存储基因链
private List<Integer> list0=new ArrayList<Integer>();//存储 1 0 数据
public gene() {
this.list0 = list0;
}
public gene(int j) {//随机构造长度为j的数据链
List list=new ArrayList<Integer>();
for(int i=0;i<j;i++){
double a = Math.random();
a=10*a;
a= (int) a;
if(a%2==0)a=0;
else a=1;
list.add((int)a);
}
this.list0 = list;
}
public gene(ArrayList list0) {
this.list0 = list0;
}
public List getList0() {
return list0;
}
public void setList0(ArrayList list0) {
this.list0 = list0;
}
public gene mutation() {//突变方法
// gene gene1=new gene(6);
gene gene2=new gene();
for (Integer i:this.list0){
double a = Math.random();
if(a<0.011){
if(i==1)i=0;
else i=1;
gene2.getList0().add(i);
}
else{
gene2.getList0().add(i);
}
}
return gene2;
}
public gene mating(gene gene0) {//基因交换方法
gene gene1=new gene();
int b=1;
while(b==1){
// for (int l=0;l<gene2.getList0().size();l++){
// gene2.getList0().remove(gene2.getList0().get(l));
// }
for (int i=0;i<6;i++){
double a = Math.random();
if(a<0.17&&b==1){
gene1.getList0().addAll(gene0.getList0().subList(6*i,6*(i+1)));
b--;
}
else{
gene1.getList0().addAll(this.getList0().subList(6*i,6*(i+1)));
}
}
}
return gene1;
}
public double dv(gene gene0) {//计算本条基因与笑脸的差的平方和
double d;
d=0;
int i=0;
for (Integer a:this.list0){
i++;int j=0;
for (Integer b:gene0.list0){
j++;
if(i==j){
d=d+(a-b)*(a-b);
}
}
}
return d;
}
@Override
public String toString() {
return "gene{" +
"list0=" + list0 +
'}';
}
public void iprint(int j) {//重写的打印方法将【1,0】数据链输出为矩阵
List<String> list=new ArrayList<>();
for (Integer a:list0){
if (a==0)list.add("十");
else list.add("黑");
}
for(int i=0;i<j;i++){
System.out.println(list.subList(i*j,(i+1)*j));
}
// int i=0;
// for (Integer a:list0){
// System.out.println(a);i++;
// if(i%j==0){System.out.println("\n");}
// }
}
}
执行类:
import genepack.gene;
import java.util.*;
public class test1 {
public static void main(String[] args) {
List<gene> list1 = new ArrayList<gene>();
List<gene> list2 = new ArrayList<gene>();
gene gene01 =new gene();//笑脸图像的初始化
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(1);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(1);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(1);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(1);
gene01.getList0().add(0);
gene01.getList0().add(1);
gene01.getList0().add(1);
gene01.getList0().add(1);
gene01.getList0().add(1);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene01.getList0().add(0);
gene gene1 =new gene(36);//五个随机亲本
gene gene2 =new gene(36);
gene gene3 =new gene(36);
gene gene4 =new gene(36);
gene gene5 =new gene(36);
list1.add(gene1);
list1.add(gene2);
list1.add(gene3);
list1.add(gene4);
list1.add(gene5);
gene01.iprint(6);//输出笑脸
int p=1;int count=0;
while (p==1) {//不断迭代寻找结果
list2.addAll(list1);
for (gene g : list1) {//本循环执行基因交换
int d = 1;
while (d == 1) {
for (genepack.gene gene : list1) {
if (!gene.equals(g)) {
double a = Math.random();
if (a < 0.2 && d == 1) {
list2.add(g.mating(gene));
d--;
}
}
}
}
}
list2.sort(new Comparator<gene>() { //排序方法重写
@Override
public int compare(gene o1, gene o2) {
if (o1 != null && o2 != null) {
if (o1.dv(gene01) >= o2.dv(gene01)) {
return 1;
} else if (o1.dv(gene01) < o2.dv(gene01)) {
return -1;
} else {
return -1;
}
}
if (o1 != null) {
return 1;
}
if (o2 != null) {
return -1;
}
return 0;
}
});
System.out.println("-----------------");
int u = 1;
u = 1;
for (gene o : list2) {
if (u == 1) {
if (o.dv(gene01)==0){
p=0;
}
System.out.println(o.dv(gene01));
System.out.println(count+"代");count++;
o.iprint(6);
u--;
}
}
System.out.println("-----------------");
list1.removeAll(list1);
for (gene o : list2.subList(0, 5)) {
o.setList0((ArrayList) o.mutation().getList0());//亲代与子代都进行基因突变
}
list1.addAll(list2.subList(0, 5));
list2.removeAll(list2);
}
}
}