您的位置:首页 > 其它

遗传算法实现机器人寻路

2017-09-23 11:23 99 查看
package com.louis.robot;

/**
* Project Name:GeneticAlgorithm
* File Name:Individual.java
* Package Name:
* Date:2017年9月23日下午5:02:00
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/

/**
* ClassName:Individual
* Function: 个体类
* Reason:     TODO ADD REASON.
* Date:     2017年9月23日 下午5:02:00
* @author   michael
* @version
* @since    JDK 1.7
* @see
*/
public class Individual {
//定义染色体,染色体是要很多基因组成
private int[] chromosome;
//定义个体实现度,默认值是-1
private double fitness = -1;
/*
* 通过特定染色体创建个体
* */
public Individual(int[] chromosome){
this.chromosome = chromosome;
}
/*
* 通过随机基因创建个体:染色上的基因是随机数产生的
* */
public Individual(int chromosomeLength){
this.chromosome = new int[chromosomeLength];
for (int gene = 0; gene < chromosomeLength; gene++) {
if(0.5<Math.random()){
this.setGene(gene, 1);
}
else {
this.setGene(gene, 0);
}
}
}
/*
* get 个体的基因
* */
public int[] getChromosome(){
return this.chromosome;
}

/*
* get 基因的长度
* */
public int getChromosomeLength(){
return this.chromosome.length;
}
/*
* 在特定的地方设置基因
* */
public void setGene(int offset,int gene){
this.chromosome[offset] = gene;
}

/*
* 在特定的地方得到基因
* */
public int getGene(int offset){
return this.chromosome[offset];
}
/*
* 设置个体适应度
* */
public void setFitness(double fitness){
this.fitness = fitness;
}
/*
* 得到个体适应度
* */
public double getFitness(){
return this.fitness;
}
/*
* 染色体(即所有基因)以字符串的形式打印
* */
public String toString(){
String output = "";
for (int gene = 0; gene < this.chromosome.length; gene++) {
output +=this.chromosome[gene];
}
return output;
}
}
package com.louis.robot;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;

import org.apache.jasper.tagplugins.jstl.core.If;

/**

* Project Name:GeneticAlgorithm
* File Name:Population.java
* Package Name:
* Date:2017年9月23日下午7:44:55
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/

/**
* ClassName:Population
* Function: 种群类
* Reason:     TODO ADD REASON.
* Date:     2017年9月23日 下午7:44:55
* @author   michael
* @version
* @since    JDK 1.7
* @see
*/
public class Population {
//种群:所有个体的集合
public Individual[] population;
//种群适应度
public double populationFitness=-1;
/*
* 初始化一个空的种群,参数是种群的大小
* */
public Population(int populationSize){
this.population = new Individual[populationSize];
}
/*
* 初始化种群,参数是:(1)种群的大小,(2)染色体的长度
* */
public Population(int populationSize,int chromosomeLength){
//新建一个种群,即所有个体的集合
this.population = new Individual[populationSize];
//创建种群中的每个个体
for (int individualCount = 0; individualCount < populationSize; individualCount++) {
//调用Individual类的构造方法,创建个体
Individual individual = new Individual(chromosomeLength);
//将该个体添加到种群中
this.population[individualCount] = individual;
}
}
/*
* 从种群中得到所有个体
* */
public Individual[] getIndividuals(){
return this.population;
}
/*
*通过个体适应度选择一个个体
*先将种群进行排序,最后获得第offset位置的个体
*按适应度顺序排列个体
*从高到底排序
* */
public Individual getFittest(int offset){
//对种群中的个体按照适应度进行排序
Arrays.sort(this.population, new Comparator<Individual>() {

@Override
public int compare(Individual o1, Individual o2) {
if(o1.getFitness()>o2.getFitness()){
return -1;
}
else if(o1.getFitness()<o2.getFitness()){
return 1;
}
return 0;
}   //Arrays.sort(数组,比较器<数组类型>)

});
//返回排序第offset的个体
return this.population[offset];
}
/*
* 得到种群适应度
* */
public double getPopulationFitness() {
return populationFitness;
}

/*
* 设置种群适应度
* */
public void setPopulationFitness(double populationFitness) {
this.populationFitness = populationFitness;
}
/*
* 得到种群的大小
* */
public int size(){
return this.population.length;
}
/*
* 在第offset位置设置个体
* */
public Individual setIndividual(int offset,Individual individual){
return population[offset] = individual;
}
/*
* 得到第offset位置的个体
* */
public Individual getIndividual(int offset){
return population[offset];
}
/*
* 随机洗牌
* */
public void shuffle() {
Random rnd = new Random();
for (int i = population.length - 1; i > 0; i--) {
int index = rnd.nextInt(i + 1);
Individual a = population[index];
population[index] = population[i];
population[i] = a;
}
}
}
/**
* Project Name:GeneticAlgorithm
* File Name:Maze.java
* Package Name:com.louis.rebot
* Date:2017年9月24日上午9:38:37
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/

package com.louis.robot;

import java.util.ArrayList;

/**
* ClassName:Maze
* Function: 迷宫类
* Reason:
* 0 = Empty
* 1 = Wall
* 2 = Starting position
* 3 = Route
* 4 = Goal position
* Date:     2017年9月24日 上午9:38:37
* @author   michael
* @version
* @since    JDK 1.7
* @see
*/
public class Maze {
private final int maze[][];
private int startPosition[] = {-1,-1};

public Maze(int maze[][]){
this.maze = maze;
}
/*
* 得到起始位置
* */
public int[] getStartPosition(){
//确认已经找到起始位置
if(this.startPosition[0]!=-1&&this.startPosition[1]!=-1){
return this.startPosition;
}
//返回默认值
int startPosition[] = {0,0};
//遍历
for (int rowIndex = 0; rowIndex < this.maze.length; rowIndex++) {
for (int colIndex = 0; colIndex < this.maze[rowIndex].length; colIndex++) {
//找坐标值是2的坐标
if(this.maze[rowIndex][colIndex]==2){
this.startPosition = new int[]{colIndex,rowIndex};
return new int[]{colIndex,rowIndex};
}
}
}
return startPosition;
}

/*
* 得到具体位置上的值
* */
public int getPositionValue(int x,int y){
//在指定范围以外的坐标值为1,即是墙
if(x<0||y<0||x>=this.maze.length||y>=this.maze[0].length){
return 1;
}
return this.maze[y][x];
}

/*
* 判断是否是墙
* */
public boolean isWall(int x,int y){
return (this.getPositionValue(x, y)==1);
}

/*
* 得到x的最大值,列数-1
* */
public int getMaxX(){
return this.maze[0].length-1;
}
/*
* 得到y的最大值,行数-1
* */
public int getMaxY(){
return this.maze.length-1;
}
/*
* 评估采取的路径,基于踩到的正确地砖的数目
* route是路线,Arrlist类型,里面的数组代表的是经过的坐标点
* */
public int scoreRoute(ArrayList<int[]> route){
int score = 0;
boolean visited[][] = new boolean[this.getMaxY()+1][this.getMaxX()+1];
for(Object routeStep:route){
int step[] = (int[])routeStep;
if(this.maze[step[1]][step[0]]==3 && visited[step[1]][step[0]]==false){
score++;
//已经访问过
visited[step[1]][step[0]] = true;
}
}
return score;
}
}
/**
* Project Name:GeneticAlgorithm
* File Name:Robot.java
* Package Name:com.louis.rebot
* Date:2017年9月24日上午9:38:50
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/

package com.louis.robot;

import java.util.ArrayList;

/**
* ClassName:Robot
* Function: 机器人类
* Reason:     TODO ADD REASON.
* Date:     2017年9月24日 上午9:38:50
* @author   michael
* @version
* @since    JDK 1.7
* @see
*/
public class Robot {
//定义方向
private enum Direction{NORTH,EAST,SOUTH,WEST};

private int xPosition;
private int yPosition;
//下一步前往的方向
private Direction heading;
//最大移动步数
int maxMoves;
//当前移动了多少步
int moves;
//传感器的值
private int sensorVal;
//传感器行为数组
private final int sensorActions[];
//迷宫
private Maze maze;
//行走路线
private ArrayList<int[]> route;
public Robot(int[] sensorActions, Maze maze, int maxMoves){
this.sensorActions = this.calcSensorActions(sensorActions);
this.maze = maze;
int startPos[] = this.maze.getStartPosition();
this.xPosition = startPos[0];
this.yPosition = startPos[1];
this.sensorVal = -1;
this.heading = Direction.EAST;
this.maxMoves = maxMoves;
this.moves = 0;
this.route = new ArrayList<int[]>();
this.route.add(startPos);
}
//基于传感器的输入运行机器人的行为
public void run(){
while(true){
this.moves++;

//机器人的下一步移动到为0
if (this.getNextAction() == 0) {
return;
}
//如果到达目的地
if (this.maze.getPositionValue(this.xPosition, this.yPosition) == 4) {
return;
}
//如果步数大于最大步数
if (this.moves > this.maxMoves) {
return;
}
//继续往前走
this.makeNextAction();
}
}
/*
* 将字符串类型的传感器数据映射成行为
* */
private int[] calcSensorActions(int[] sensorActionsStr){
//多少个动作:一个动作,需要两位传感器数据
int numActions = (int)sensorActionsStr.length/2;
int sensorActions[] = new int[numActions];

for (int sensorValue = 0; sensorValue < numActions; sensorValue++){
//每次循环,sensorAtion都初始化为0
int sensorAction = 0;
if (sensorActionsStr[sensorValue*2] == 1){
sensorAction += 2;
}
if (sensorActionsStr[(sensorValue*2)+1] == 1){
sensorAction += 1;
}

//加入到行为数组中
sensorActions[sensorValue] = sensorAction;
}
return sensorActions;
}

/*
* 下一步执行什么操作
* */
public void makeNextAction(){
// 向前移动
if (this.getNextAction() == 1) {
int currentX = this.xPosition;
int currentY = this.yPosition;

// 向前移动取决于当前的机器人面朝哪
if (Direction.NORTH == this.heading) {
this.yPosition += -1;
if (this.yPosition < 0) {
this.yPosition = 0;
}
}
else if (Direction.EAST == this.heading) {
this.xPosition += 1;
if (this.xPosition > this.maze.getMaxX()) {
this.xPosition = this.maze.getMaxX();
}
}
else if (Direction.SOUTH == this.heading) {
this.yPosition += 1;
if (this.yPosition > this.maze.getMaxY()) {
this.yPosition = this.maze.getMaxY();
}
}
else if (Direction.WEST == this.heading) {
this.xPosition += -1;
if (this.xPosition < 0) {
this.xPosition = 0;
}
}

// 不能移动
if (this.maze.isWall(this.xPosition, this.yPosition) == true) {
this.xPosition = currentX;
this.yPosition = currentY;
}
else {
if(currentX != this.xPosition || currentY != this.yPosition) {
this.route.add(this.getPosition());
}
}
}
// 顺时针移动
else if(this.getNextAction() == 2) {
if (Direction.NORTH == this.heading) {
this.heading = Direction.EAST;
}
else if (Direction.EAST == this.heading) {
this.heading = Direction.SOUTH;
}
else if (Direction.SOUTH == this.heading) {
this.heading = Direction.WEST;
}
else if (Direction.WEST == this.heading) {
this.heading = Direction.NORTH;
}
}
// 逆时针移动
else if(this.getNextAction() == 3) {
if (Direction.NORTH == this.heading) {
this.heading = Direction.WEST;
}
else if (Direction.EAST == this.heading) {
this.heading = Direction.NORTH;
}
else if (Direction.SOUTH == this.heading) {
this.heading = Direction.EAST;
}
else if (Direction.WEST == this.heading) {
this.heading = Direction.SOUTH;
}
}

// 重新设置传感器的值
this.sensorVal = -1;
}

/*
* 得到下一步的操作
* */
public int getNextAction() {
return this.sensorActions[this.getSensorValue()];
}

/*
* 得到传感器的值
* */
public int getSensorValue(){
// If sensor value has already been calculated
if (this.sensorVal > -1) {
return this.sensorVal;
}

boolean frontSensor, frontLeftSensor, frontRightSensor, leftSensor, rightSensor, backSensor;
frontSensor = frontLeftSensor = frontRightSensor = leftSensor = rightSensor = backSensor = false;

// 机器人是朝哪个方向走的
if (this.getHeading() == Direction.NORTH) {
frontSensor = this.maze.isWall(this.xPosition, this.yPosition-1);
frontLeftSensor = this.maze.isWall(this.xPosition-1, this.yPosition-1);
frontRightSensor = this.maze.isWall(this.xPosition+1, this.yPosition-1);
leftSensor = this.maze.isWall(this.xPosition-1, this.yPosition);
rightSensor = this.maze.isWall(this.xPosition+1, this.yPosition);
backSensor = this.maze.isWall(this.xPosition, this.yPosition+1);
}
else if (this.getHeading() == Direction.EAST) {
frontSensor = this.maze.isWall(this.xPosition+1, this.yPosition);
frontLeftSensor = this.maze.isWall(this.xPosition+1, this.yPosition-1);
frontRightSensor = this.maze.isWall(this.xPosition+1, this.yPosition+1);
leftSensor = this.maze.isWall(this.xPosition, this.yPosition-1);
rightSensor = this.maze.isWall(this.xPosition, this.yPosition+1);
backSensor = this.maze.isWall(this.xPosition-1, this.yPosition);
}
else if (this.getHeading() == Direction.SOUTH) {
frontSensor = this.maze.isWall(this.xPosition, this.yPosition+1);
frontLeftSensor = this.maze.isWall(this.xPosition+1, this.yPosition+1);
frontRightSensor = this.maze.isWall(this.xPosition-1, this.yPosition+1);
leftSensor = this.maze.isWall(this.xPosition+1, this.yPosition);
rightSensor = this.maze.isWall(this.xPosition-1, this.yPosition);
backSensor = this.maze.isWall(this.xPosition, this.yPosition-1);
}
else {
frontSensor = this.maze.isWall(this.xPosition-1, this.yPosition);
frontLeftSensor = this.maze.isWall(this.xPosition-1, this.yPosition+1);
frontRightSensor = this.maze.isWall(this.xPosition-1, this.yPosition-1);
leftSensor = this.maze.isWall(this.xPosition, this.yPosition+1);
rightSensor = this.maze.isWall(this.xPosition, this.yPosition-1);
backSensor = this.maze.isWall(this.xPosition+1, this.yPosition);
}

// Calculate sensor value
int sensorVal = 0;

if (frontSensor == true) {
sensorVal += 1;
}
if (frontLeftSensor == true) {
sensorVal += 2;
}
if (frontRightSensor == true) {
sensorVal += 4;
}
if (leftSensor == true) {
sensorVal += 8;
}
if (rightSensor == true) {
sensorVal += 16;
}
if (backSensor == true) {
sensorVal += 32;
}

this.sensorVal = sensorVal;

return sensorVal;
}

/*
* 返回机器人行走路径
* */
public ArrayList<int[]> getRoute(){
return this.route;
}
/*
* 获取机器人坐标
* */
public int[] getPosition(){
return new int[]{this.xPosition, this.yPosition};
}
/*
* 机器人下一个方向
* */
private Direction getHeading(){
return this.heading;
}
/*
* 打印机器人行走路径
* */
public String printRoute() {
String route = "";

for (Object routeStep : this.route) {
int step[] = (int[]) routeStep;
route += "{" + step[0] + "," + step[1] + "}";
}
return route;
}
}
package com.louis.robot;

import com.sun.org.apache.bcel.internal.generic.PopInstruction;

/**
* Project Name:GeneticAlgorithm
* File Name:GeneticAlgorithm.java
* Package Name:
* Date:2017年9月23日下午8:25:25
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/

/**
* ClassName:GeneticAlgorithm
* Function: 遗传算法的核心
* Reason:     TODO ADD REASON.
* Date:     2017年9月23日 下午8:25:25
* @author   michael
* @version
* @since    JDK 1.7
* @see
*/
public class GeneticAlgorithm {
/*种群大小*/
private int populationSize;
/*变异概率*/
private double mutationRate;
/*交叉概率*/
private double crossoverRate;
/*精英个体数:种群中最强的个体数。保持原样,不参与交叉和变异*/
private int elitismCount;
//锦标大小
private int tournamentSize;
/*构造函数*/
public GeneticAlgorithm(int populationSize, double mutationRate,
double crossoverRate, int elitismCount, int tournamentSize) {
super();
this.populationSize = populationSize;
this.mutationRate = mutationRate;
this.crossoverRate = crossoverRate;
this.elitismCount = elitismCount;
this.tournamentSize = tournamentSize;
}
/*
* 调用population的构造方法,使用染色体长度初始化种群
* */
public Population initPopulation(int chromosomeLength){
Population population = new Population(this.populationSize, chromosomeLength);
return population;
}

/*
* 计算一个个体的适应度
* */
public double calcFitness(Individual individual, Maze maze) {
// 得到个体基因
int[] chromosome = individual.getChromosome();

// 得到适应度
Robot robot = new Robot(chromosome, maze, 100);
robot.run();
int fitness = maze.scoreRoute(robot.getRoute());

// 保存适应度
individual.setFitness(fitness);

return fitness;
}

/*
* 遍历每个个体评估种群适应度
* */
public void evalPopulation(Population population, Maze maze) {
double populationFitness = 0;

//遍历每个个体统计种群总适应度
for (Individual individual : population.getIndividuals()) {
populationFitness += this.calcFitness(individual, maze);
}

population.setPopulationFitness(populationFitness);
}
/*
* 判断终止的条件,最大代数
* */
public boolean isTerminationConditionMet(int generationsCount, int maxGenerations) {
return (generationsCount > maxGenerations);
}
/*
* 选择交叉的个体
* */
public Individual selectParent(Population population) {
// 创建用于锦标赛的种群
Population tournament = new Population(this.tournamentSize);

//随机洗牌
population.shuffle();
// 随机向锦标赛插入个体
for (int i = 0; i < this.tournamentSize; i++) {
Individual tournamentIndividual = population.getIndividual(i);
tournament.setIndividual(i, tournamentIndividual);
}
// 返回最好的个体
return tournament.getFittest(0);
}
/*
* 单点交叉:返回一个新的种群
* */
public Population crossoverPopulation(Population population) {
// 重新创建一个种群
Population newPopulation = new Population(population.size());

// 按适应度遍历原来的种群
for (int populationIndex = 0; populationIndex < population.size(); populationIndex++) {
//因为已经按照适应度对种群进行排序了,所以这里是从小往大选择
Individual parent1 = population.getFittest(populationIndex);

// 是否交叉,交叉率大于随机数并且pass掉精英个体
if (this.crossoverRate > Math.random() && populationIndex >= this.elitismCount) {
// 初始化下一代个体
Individual offspring = new Individual(parent1.getChromosomeLength());

// 通过锦标赛选择第二个父个体
Individual parent2 = this.selectParent(population);

// 随机产生交叉点
int swapPoint = (int) (Math.random() * (parent1.getChromosomeLength() + 1));

for (int geneIndex = 0; geneIndex < parent1.getChromosomeLength(); geneIndex++) {
// 在交叉点前用1的基因,交叉点后用2的
if (geneIndex < swapPoint) {
offspring.setGene(geneIndex, parent1.getGene(geneIndex));
} else {
offspring.setGene(geneIndex, parent2.getGene(geneIndex));
}
}

// 将子个体加入到种群中
newPopulation.setIndividual(populationIndex, offspring);
} else {
// 没有交叉的个体直接加入到种群中,精英个体
newPopulation.setIndividual(populationIndex, parent1);
}
}

return newPopulation;
}

/*变异得到新种群*/
public Population mutatePopulation(Population population){
Population newPopulation = new Population(this.populationSize);
//通过适应度遍历当前种群
for (int populationIndex = 0; populationIndex < population.size(); populationIndex++) {
//按照从小到大的顺序选择个体
Individual individual = population.getFittest(populationIndex);
//遍历个体的基因
for (int geneIndex = 0; geneIndex < individual.getChromosomeLength(); geneIndex++) {
if(populationIndex>this.elitismCount){
//判断该基因是否变异
if(this.mutationRate>Math.random()){
int newGene = 1;
if(individual.getGene(geneIndex)==1){
newGene = 0;
}
//变异基因
individual.setGene(geneIndex, newGene);
}

}
}
newPopulation.setIndividual(populationIndex, individual);
}
return newPopulation;
}

}
/**
* Project Name:GeneticAlgorithm
* File Name:RobotController.java
* Package Name:com.louis.robot
* Date:2017年9月24日上午9:39:50
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/

package com.louis.robot;

/**
* ClassName:RobotController
* Function: 执行类
* Reason:     TODO ADD REASON.
* Date:     2017年9月24日 上午9:39:50
* @author   michael
* @version
* @since    JDK 1.7
* @see
*/
public class RobotController {
//设置最大的代
public static int maxGenerations = 1000;

public static void main(String[] args) {
//创建迷宫
Maze maze = new Maze(new int[][] {
{ 0, 0, 0, 0, 1, 0, 1, 3, 2 },
{ 1, 0, 1, 1, 1, 0, 1, 3, 1 },
{ 1, 0, 0, 1, 3, 3, 3, 3, 1 },
{ 3, 3, 3, 1, 3, 1, 1, 0, 1 },
{ 3, 1, 3, 3, 3, 1, 1, 0, 0 },
{ 3, 3, 1, 1, 1, 1, 0, 1, 1 },
{ 1, 3, 0, 1, 3, 3, 3, 3, 3 },
{ 0, 3, 1, 1, 3, 1, 0, 1, 3 },
{ 1, 3, 3, 3, 3, 1, 1, 1, 4 }
});

//创建遗传算法
GeneticAlgorithm ga = new GeneticAlgorithm(200, 0.05, 0.9, 2, 10);
Population population = ga.initPopulation(128);

/*
* 评估种群
* */
ga.evalPopulation(population, maze);

int generation =1;

/*
* 开始进化
* */
while (ga.isTerminationConditionMet(generation, maxGenerations) == false) {
// 打印种群中适应度最好的个体
Individual fittest = population.getFittest(0);
System.out.println("G" + generation + " Best solution ("
+ fittest.getFitness() + "): " + fittest.toString());

// 交叉
population = ga.crossoverPopulation(population);

// 变异
population = ga.mutatePopulation(population);

// 评估种群
ga.evalPopulation(population, maze);

// 迭代
generation++;
}

System.out.println("Stopped after " + maxGenerations + " generations.");
Individual fittest = population.getFittest(0);
System.out.println("Best solution (" + fittest.getFitness() + "): "
+ fittest.toString());

}

}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: