设为首页 加入收藏

TOP

遗传算法在走迷宫游戏中的应用(二)
2015-11-21 01:52:09 来源: 作者: 【 】 浏览:2
Tags:遗传 算法 迷宫 游戏 应用
ble[] adaptiveva lue = new double[initSetsNum]; for (int i = 0; i < initSetsNum; i++) { adaptiveva lue[i] = calFitness(initCodes.get(i)); sumFitness += adaptiveva lue[i]; } // 转成概率的形式,做归一化操作 for (int i = 0; i < initSetsNum; i++) { adaptiveva lue[i] = adaptiveva lue[i] / sumFitness; } for (int i = 0; i < initSetsNum; 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 (int j = 0; j < initSetsNum; j++) { if (randomNum > sumFitness && randomNum <= sumFitness + adaptiveva lue[j]) { // 采用拷贝的方式避免引用重复 resultCodes.add(initCodes.get(j).clone()); break; } else { sumFitness += adaptiveva lue[j]; } } } return resultCodes; } /** * 交叉运算 * * @param selectedCodes * 上步骤的选择后的编码 * @return */ private ArrayList crossOperate(ArrayList selectedCodes) { int randomNum = 0; // 交叉点 int crossPoint = 0; ArrayList resultCodes = new ArrayList<>(); // 随机编码队列,进行随机交叉配对 ArrayList randomCodeSeqs = new ArrayList<>(); // 进行随机排序 while (selectedCodes.size() > 0) { randomNum = random.nextInt(selectedCodes.size()); randomCodeSeqs.add(selectedCodes.get(randomNum)); selectedCodes.remove(randomNum); } int temp = 0; int[] array1; int[] array2; // 进行两两交叉运算 for (int i = 1; i < randomCodeSeqs.size(); i++) { if (i % 2 == 1) { array1 = randomCodeSeqs.get(i - 1); array2 = randomCodeSeqs.get(i); crossPoint = random.nextInt(stepNum - 1) + 1; // 进行交叉点位置后的编码调换 for (int j = 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); } } return resultCodes; } /** * 变异操作 * * @param crossCodes * 交叉运算后的结果 * @return */ private ArrayList variationOperate(ArrayList crossCodes) { // 变异点 int variationPoint = 0; ArrayList resultCodes = new ArrayList<>(); for (int[] array : crossCodes) { variationPoint = random.nextInt(stepNum); for (int i = 0; i < array.length; i += 2) { // 变异点进行变异 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); } return resultCodes; } /** * 根据编码计算适值 * * @param code * 当前的编码 * @return */ public double calFitness(int[] code) { double fintness = 0; // 由编码计算所得的终点横坐标 int endX = 0; // 由编码计算所得的终点纵坐标 int endY = 0; // 基于片段所代表的行走方向 int direction = 0; // 临时坐标点横坐标 int tempX = 0; // 临时坐标点纵坐标 int tempY = 0; endX = startPos[0]; endY = startPos[1]; for (int i = 0; i < stepNum; i++) { direction = binaryArrayToNum(new int[] { 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 < mazeData.length && tempY >= 0 && tempY < mazeData[0].length) { // 判断坐标点是否走到阻碍块 if (mazeData[tempX][tempY] != -1) { endX = tempX; endY = tempY; } } } // 根据适值函数进行适值的计算 fintness = 1.0 / (Math.abs(endX - endPos[0]) + Math.abs(endY - endPos[1]) + 1); return fintness; } /** * 根据当前编码判断是否已经找到出口位置 * * @param code * 经过若干次遗传的编码 * @return */ private boolean ifArriveEndPos(int[] code) { boolean isArrived = false; // 由编码计算所得的终点横坐标 int endX = 0; // 由编码计算所得的终点纵坐标 int endY = 0; // 基于片段所代表的行走方向 int direction = 0; // 临时坐标点横坐标 int tempX = 0; // 临时坐标点纵坐标 int tempY = 0; endX = startPos[0]; endY = startPos[1]; for (int i = 0; i < stepNum; i++) { direction = binaryArrayToNum(new int[] { 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 < mazeData.length && tempY >= 0 && tempY < mazeData[0].length) { // 判断坐标点是否走到阻碍块 if (mazeData[tempX][tempY] != -1) { endX = tempX; endY = tempY; } } } if (endX == endPos[0] && endY == endPos[1]) { isArrived = true; } return isArrived; } /** * 二进制数组转化为数字 * * @param binaryArray * 待转化二进制数组 */ private int binaryArrayToNum(int[] binaryArray) { int result = 0; for (int i = binaryArray.length - 1, k = 0; i >= 0; i--, k++) { if (binaryArray[i] == 1) { result += Math.pow(2, k); } } return result; } /** * 进行遗传算法走出迷宫 */ public void goOutMaze() { // 迭代遗传次数 int loopCount = 0; boolean canExit = false; // 结果路径 int[] resultCode = null; ArrayList initCodes; ArrayList selectedCodes; ArrayList crossedCodes; ArrayList variationCodes; // 产生初始数据集 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); } /** * 输出找到的路径 * * @param code */ private void printFindedRoute(int[] code) { if(code == null){ System.out.println("在有限的遗传进化次数内,没有找到最优路径"); return; } int tempX = startPos[0]; int tempY = startPos[1]; int direction = 0; System.out.println(MessageFormat.format( "起始点位置({0},{1}), 出口点位置({2}, {3})", tempX, tempY, endPos[0], endPos[1])); System.out.print("搜索到的结果编码:"); for(int value: code){ System.out.print("" + value); } System.out.println(); for (int i = 0, k = 1; i < code.length; i += 2, k++) { direction = binaryArrayToNum(new int[] { 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], tempX, tempY)); } } } 算法的调用类Client.java:

?

?

package GA_Maze;

/**
 * 遗传算法在走迷宫游戏的应用
 * @author lyq
 *
 */
public class Client {
	public static void main(String[] args) {
		//迷宫地图文件数据地址
		String filePath = "C:\\Users\\lyq\\Desktop\\icon\\mapData.txt";
		//初始个体数量
		int initSetsNum = 4;
		
		GATool tool = new GATool(filePath, initSetsNum);
		tool.goOutMaze();
	}

}

?

算法的输出:

我测了很多次的数据,因为有可能会一时半会搜索不出来,我设置了最大遗传次数100次。

?

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Mongodb-使用C#Drivers实现增删改.. 下一篇xtrabackup自动还原脚本v2

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: