遗传算法.docx
- 文档编号:29752028
- 上传时间:2023-07-26
- 格式:DOCX
- 页数:21
- 大小:42.77KB
遗传算法.docx
《遗传算法.docx》由会员分享,可在线阅读,更多相关《遗传算法.docx(21页珍藏版)》请在冰豆网上搜索。
遗传算法
遗
传
算
法
应
用
《人工智能导论》课程设计
学号:
13055524
姓名:
吴国庆
一、迷宫问题:
个体基因长度
首先是基于长度,因为最后筛选出的是一个个体,就是满足条件的个体,他的基因编码就是问题的最优解,所以就能联想把角色的每一步移动操作看出是一个基因编码,总共7步就需要7个基因值表示,所以基因的长度在本例子中就是7。
基因表示
已经将角色的每一次的移动步骤转化为基因的表示,每次的移动总共有4种可能,上下左右,基因编码是标准的二进制形式,所以可以取值为00代表向上,01向下,10向左,11向右,也就是说,每个基因组用2个编码表示,所以总共的编码数字就是2*7=14个,两两一对。
例子
01234
二、算法地图数据的输入mapData.txt:
010121
210-10
01001
1-100-1
012101
三、具体代码实现如下:
算法的实现类GATool.java
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileReader;
importjava.io.IOException;
importjava.text.MessageFormat;
importjava.util.ArrayList;
importjava.util.Random;
/**
*遗传算法在走迷宫游戏的应用-遗传算法工具类
*
*@authorlyq
*
*/
publicclassGATool{
//迷宫出入口标记
publicstaticfinalintMAZE_ENTRANCE_POS=1;
publicstaticfinalintMAZE_EXIT_POS=2;
//方向对应的编码数组
publicstaticfinalint[][]MAZE_DIRECTION_CODE=newint[][]{{0,0},
{0,1},{1,0},{1,1},};
//坐标点方向改变
publicstaticfinalint[][]MAZE_DIRECTION_CHANGE=newint[][]{
{-1,0},{1,0},{0,-1},{0,1},};
//方向的文字描述
publicstaticfinalString[]MAZE_DIRECTION_LABEL=newString[]{"上",
"下","左","右"};
//地图数据文件地址
privateStringfilePath;
//走迷宫的最短步数
privateintstepNum;
//初始个体的数量
privateintinitSetsNum;
//迷宫入口位置
privateint[]startPos;
//迷宫出口位置
privateint[]endPos;
//迷宫地图数据
privateint[][]mazeData;
//初始个体集
privateArrayList
//随机数产生器
privateRandomrandom;
publicGATool(StringfilePath,intinitSetsNum){
this.filePath=filePath;
this.initSetsNum=initSetsNum;
readDataFile();
}
/**
*从文件中读取数据
*/
publicvoidreadDataFile(){
Filefile=newFile(filePath);
ArrayList
try{
BufferedReaderin=newBufferedReader(newFileReader(file));
Stringstr;
String[]tempArray;
while((str=in.readLine())!
=null){
tempArray=str.split("");
dataArray.add(tempArray);
}
in.close();
}catch(IOExceptione){
e.getStackTrace();
}
introwNum=dataArray.size();
mazeData=newint[rowNum][rowNum];
for(inti=0;i String[]data=dataArray.get(i); for(intj=0;j mazeData[i][j]=Integer.parseInt(data[j]); //赋值入口和出口位置 if(mazeData[i][j]==MAZE_ENTRANCE_POS){ startPos=newint[2]; startPos[0]=i; startPos[1]=j; }elseif(mazeData[i][j]==MAZE_EXIT_POS){ endPos=newint[2]; endPos[0]=i; endPos[1]=j; } } } //计算走出迷宫的最短步数 stepNum=Math.abs(startPos[0]-endPos[0])+Math.abs(startPos[1]-endPos[1]); } /** *产生初始数据集 */ privatevoidproduceInitSet(){ //方向编码 intdirectionCode=0; random=newRandom(); initSets=newArrayList //每个步骤的操作需要用2位数字表示 int[]codeNum; for(inti=0;i codeNum=newint[stepNum*2]; for(intj=0;j directionCode=random.nextInt(4); codeNum[2*j]=MAZE_DIRECTION_CODE[directionCode][0]; codeNum[2*j+1]=MAZE_DIRECTION_CODE[directionCode][1]; } initSets.add(codeNum); } } /** *选择操作,把适值较高的个体优先遗传到下一代 * *@paraminitCodes *初始个体编码 *@return */ privateArrayList doublerandomNum=0; doublesumFitness=0; ArrayList double[]adaptiveValue=newdouble[initSetsNum]; for(inti=0;i adaptiveValue[i]=calFitness(initCodes.get(i)); sumFitness+=adaptiveValue[i]; } //转成概率的形式,做归一化操作 for(inti=0;i adaptiveValue[i]=adaptiveValue[i]/sumFitness; } for(inti=0;i randomNum=random.nextInt(100)+1; randomNum=randomNum/100; //因为1.0是无法判断到的,,总和会无限接近1.0取为0.99做判断 if(randomNum==1){ randomNum=randomNum-0.01; } sumFitness=0; //确定区间 for(intj=0;j if(randomNum>sumFitness &&randomNum<=sumFitness+adaptiveValue[j]){ //采用拷贝的方式避免引用重复 resultCodes.add(initCodes.get(j).clone()); break; }else{ sumFitness+=adaptiveValue[j]; } } } returnresultCodes; } /** *交叉运算 * *@paramselectedCodes *上步骤的选择后的编码 *@return */ privateArrayList intrandomNum=0; //交叉点 intcrossPoint=0; ArrayList //随机编码队列,进行随机交叉配对 ArrayList //进行随机排序 while(selectedCodes.size()>0){ randomNum=random.nextInt(selectedCodes.size()); randomCodeSeqs.add(selectedCodes.get(randomNum)); selectedCodes.remove(randomNum); } inttemp=0; int[]array1; int[]array2; //进行两两交叉运算 for(inti=1;i if(i%2==1){ array1=randomCodeSeqs.get(i-1); array2=randomCodeSeqs.get(i); crossPoint=random.nextInt(stepNum-1)+1; //进行交叉点位置后的编码调换 for(intj=0;j<2*stepNum;j++){ if(j>=2*crossPoint){ temp=array1[j]; array1[j]=array2[j]; array2[j]=temp; } } //加入到交叉运算结果中 resultCodes.add(array1); resultCodes.add(array2); } } returnresultCodes; } /** *变异操作 * *@paramcrossCodes *交叉运算后的结果 *@return */ privateArrayList //变异点 intvariationPoint=0; ArrayList for(int[]array: crossCodes){ variationPoint=random.nextInt(stepNum); for(inti=0;i //变异点进行变异 if(i%2==0&&i/2==variationPoint){ array[i]=(array[i]==0? 1: 0); array[i+1]=(array[i+1]==0? 1: 0); break; } } resultCodes.add(array); } returnresultCodes; } /** *根据编码计算适值 * *@paramcode *当前的编码 *@return */ publicdoublecalFitness(int[]code){ doublefintness=0; //由编码计算所得的终点横坐标 intendX=0; //由编码计算所得的终点纵坐标 intendY=0; //基于片段所代表的行走方向 intdirection=0; //临时坐标点横坐标 inttempX=0; //临时坐标点纵坐标 inttempY=0; endX=startPos[0]; endY=startPos[1]; for(inti=0;i direction=binaryArrayToNum(newint[]{code[2*i], code[2*i+1]}); //根据方向改变数组做坐标点的改变 tempX=endX+MAZE_DIRECTION_CHANGE[direction][0]; tempY=endY+MAZE_DIRECTION_CHANGE[direction][1]; //判断坐标点是否越界 if(tempX>=0&&tempX &&tempY //判断坐标点是否走到阻碍块 if(mazeData[tempX][tempY]! =-1){ endX=tempX; endY=tempY; } } } //根据适值函数进行适值的计算 fintness=1.0/(Math.abs(endX-endPos[0]) +Math.abs(endY-endPos[1])+1); returnfintness; } /** *根据当前编码判断是否已经找到出口位置 * *@paramcode *经过若干次遗传的编码 *@return */ privatebooleanifArriveEndPos(int[]code){ booleanisArrived=false; //由编码计算所得的终点横坐标 intendX=0; //由编码计算所得的终点纵坐标 intendY=0; //基于片段所代表的行走方向 intdirection=0; //临时坐标点横坐标 inttempX=0; //临时坐标点纵坐标 inttempY=0; endX=startPos[0]; endY=startPos[1]; for(inti=0;i direction=binaryArrayToNum(newint[]{code[2*i], code[2*i+1]}); //根据方向改变数组做坐标点的改变 tempX=endX+MAZE_DIRECTION_CHANGE[direction][0]; tempY=endY+MAZE_DIRECTION_CHANGE[direction][1]; //判断坐标点是否越界 if(tempX>=0&&tempX &&tempY //判断坐标点是否走到阻碍块 if(mazeData[tempX][tempY]! =-1){ endX=tempX; endY=tempY; } } } if(endX==endPos[0]&&endY==endPos[1]){ isArrived=true; } returnisArrived; } /** *二进制数组转化为数字 * *@parambinaryArray *待转化二进制数组 */ privateintbinaryArrayToNum(int[]binaryArray){ intresult=0; for(inti=binaryArray.length-1,k=0;i>=0;i--,k++){ if(binaryArray[i]==1){ result+=Math.pow(2,k); } } returnresult; } /** *进行遗传算法走出迷宫 */ publicvoidgoOutMaze(){ //迭代遗传次数 intloopCount=0; booleancanExit=false; //结果路径 int[]resultCode=null; ArrayList ArrayList ArrayList ArrayList //产生初始数据集 produceInitSet(); initCodes=initSets; while(true){ for(int[]array: initCodes){ //遗传迭代的终止条件为是否找到出口位置 if(ifArriveEndPos(array)){ resultCode=array; canExit=true; break; } } if(canExit){ break; } selectedCodes=selectOperate(initCodes); crossedCodes=crossOperate(selectedCodes); variationCodes=variationOperate(crossedCodes); initCodes=variationCodes; loopCount++; //如果遗传次数超过100次,则退出 if(loopCount>=100){ break; } } System.out.println("总共遗传进化了"+loopCount+"次"); printFindedRoute(resultCode); } /** *输出找到的路径 * *@paramcode */ privatevoidprintFindedRoute(int[]code){ if(code==null){ System.out.println("在有限的遗传进化次数内,没有找到最优路径"); return; } inttempX=startPos[0]; inttempY=startPos[1]; intdirection=0; System.out.println(MessageFormat.format( "起始点位置({0},{1}),出口点位置({2},{3})",tempX,tempY,endPos[0], endPos[1])); System.out.print("搜索到的结果编码: "); for(intvalue: code){ System.out.print(""+value); } System.out.println(); for(inti=0,k=1;i direction=binaryArrayToNum(newint[]{code[i],code[i+1]}); tempX+=MAZE_DIRECTION_CHANGE[direction][0]; tempY+=MAZE_DIRECTION_CHANGE[direction][1]; System.out.println(MessageFormat.format( "第{0}步,编码为{1}{2},向{3}移动,移动后到达({4},{5})",k,code[i],code[i+1], MAZE_DIRECTION_LABEL[direction],tem
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 遗传 算法