package com.louis.tsp;

/**
* 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) {
int[] individual;
individual = new int[chromosomeLength];
//按顺序生成初始基因
for (int gene = 0; gene < chromosomeLength; gene++) {
individual[gene] = gene;
} this.chromosome = individual;
}
/*
* 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;
}
/*
* 判断是否包含该基因
* */
public boolean containsGene(int gene) {
for (int i = 0; i < this.chromosome.length; i++) {
if (this.chromosome[i] == gene) {
return true;
}
}
return false;
}
}
package com.louis.tsp;
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:City.java
* Package Name:com.louis.tsp
* Date:2017年10月5日下午4:29:03
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/ package com.louis.tsp;
/**
* ClassName:City
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2017年10月5日 下午4:29:03
* @author michael
* @version
* @since JDK 1.7
* @see
*/
public class City {
private int x;
private int y; public City(int x, int y) {
this.x = x;
this.y = y;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
} public double distanceFrom(City city){
double deltaXSq = Math.pow((city.getX() - this.getX()), 2);
double deltaYSq = Math.pow((city.getY() - this.getY()), 2);
double distance = Math.sqrt(Math.abs(deltaXSq + deltaYSq));
return distance;
}
}
/**
* Project Name:GeneticAlgorithm
* File Name:Route.java
* Package Name:com.louis.tsp
* Date:2017年10月5日下午4:49:45
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/ package com.louis.tsp; /**
* ClassName:Route
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2017年10月5日 下午4:49:45
* @author michael
* @version
* @since JDK 1.7
* @see
*/
public class Route {
private City route[];
private double distance = 0;
//保存当前路线
public Route(Individual individual, City cities[]) {
// 获取个体基因,即一条路线
int chromosome[] = individual.getChromosome();
// 将基因转化成路线
this.route = new City[cities.length];
for (int geneIndex = 0; geneIndex < chromosome.length; geneIndex++) {
this.route[geneIndex] = cities[chromosome[geneIndex]];
}
} //计算线路的总路程
public double getDistance(){
if(this.distance>0){
return this.distance;
}
double totalDistance = 0;
//循环加上路程
for (int cityIndex = 0; cityIndex + 1 < this.route.length; cityIndex++) {
totalDistance += this.route[cityIndex].distanceFrom(this.route[cityIndex + 1]);
}
//最后一个节点与第一个节点之间的路程
totalDistance += this.route[this.route.length - 1].distanceFrom(this.route[0]);
this.distance = totalDistance; return totalDistance;
}
}
package com.louis.tsp;

import java.util.Arrays;

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, City cities[]) {
// 计算适应度
Route route = new Route(individual, cities);
double fitness = 1 / route.getDistance(); // 保存个体适应度
individual.setFitness(fitness); return fitness;
}
/*
* 遍历每个个体评估种群适应度
* */
public void evalPopulation(Population population, City cities[]) {
double populationFitness = 0; //遍历每个个体,计算种群适应度
for (Individual individual : population.getIndividuals()) {
populationFitness += this.calcFitness(individual, cities);
} double avgFitness = populationFitness / population.size();
population.setPopulationFitness(avgFitness);
}
/*
* 判断终止的条件,最大代数
* */
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 parent2 = this.selectParent(population); //创建空白子代基因组
int offspringChromosome[] = new int[parent1.getChromosomeLength()];
//基因初始值都设为-1
Arrays.fill(offspringChromosome, -1);
Individual offspring = new Individual(offspringChromosome); //随机得到parent的两个位置,用于交叉
int substrPos1 = (int) (Math.random() * parent1.getChromosomeLength());
int substrPos2 = (int) (Math.random() * parent1.getChromosomeLength()); //因为不知道随机数哪个值大哪个小,所以先判断下
final int startSubstr = Math.min(substrPos1, substrPos2);
final int endSubstr = Math.max(substrPos1, substrPos2); //将落在区域的基因加入到子代基因中
for (int i = startSubstr; i < endSubstr; i++) {
offspring.setGene(i, parent1.getGene(i));
} //遍历parent2的基因
for (int i = 0; i < parent2.getChromosomeLength(); i++) {
//endSubStr后的位置
int parent2Gene = i + endSubstr;
//如果parent2的基因大于了基因长度,则减去基因长度,总的下来还是能找到所有基因
if (parent2Gene >= parent2.getChromosomeLength()) {
parent2Gene -= parent2.getChromosomeLength();
} //如果子个体没有这个基因(即城市),则加入他
if (offspring.containsGene(parent2.getGene(parent2Gene)) == false) {
// 循环找到子个体空余位置
for (int ii = 0; ii < offspring.getChromosomeLength(); ii++) {
// 找到空余位置
if (offspring.getGene(ii) == -1) {
//将父基因加入到子基因
offspring.setGene(ii, parent2.getGene(parent2Gene));
break;
}
}
}
} // 将子个体加入到种群中
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 newGenePos = (int) (Math.random() * individual.getChromosomeLength());
// 得到两个交换位置的值
int gene1 = individual.getGene(newGenePos);
int gene2 = individual.getGene(geneIndex);
// 交换基因
individual.setGene(geneIndex, gene1);
individual.setGene(newGenePos, gene2);
} }
}
newPopulation.setIndividual(populationIndex, individual);
}
return newPopulation;
} }
/**
* Project Name:GeneticAlgorithm
* File Name:TSP.java
* Package Name:com.louis.tsp
* Date:2017年10月5日下午4:36:39
* Copyright (c) 2017, 2692613726@qq.com All Rights Reserved.
*
*/ package com.louis.tsp; /**
* ClassName:TSP
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2017年10月5日 下午4:36:39
* @author michael
* @version
* @since JDK 1.7
* @see
*/
public class TSP {
public static int maxGenerations = 3000;
public static void main(String[] args) {
//100个城市
int numCities = 100;
City cities[] = new City[numCities]; // 循环随机产生100座城市坐标
for (int cityIndex = 0; cityIndex < numCities; cityIndex++) {
int xPos = (int) (100 * Math.random());
int yPos = (int) (100 * Math.random());
//添加到城市数组中
cities[cityIndex] = new City(xPos, yPos);
}
//初始化基因算法,100个基因,变异概率0.001,交叉概率0.9,精英个体5个
GeneticAlgorithm ga = new GeneticAlgorithm(100, 0.001, 0.9, 2, 5);
//初始化种群
Population population = ga.initPopulation(cities.length);
//评估种群
ga.evalPopulation(population, cities);
//当前种群年代
int generation = 1; while(ga.isTerminationConditionMet(generation, maxGenerations)==false){
//从种群中选择最优的个体:即可以打印出在该最优情况下的路线
Route route = new Route(population.getFittest(0), cities);
System.out.println("G"+generation+" 最好距离: " + route.getDistance());
//交叉
population = ga.crossoverPopulation(population);
//变异
population = ga.mutatePopulation(population);
//评估
ga.evalPopulation(population, cities);
//迭代
generation++;
} //展示结果
System.out.println("结束" + maxGenerations + " 次迭代");
Route route = new Route(population.getFittest(0), cities);
System.out.println("最好距离: " + route.getDistance());
}
}

遗传算法求解TSP问题的更多相关文章

  1. 利用遗传算法求解TSP问题

    转载地址 https://blog.csdn.net/greedystar/article/details/80343841 目录 一.问题描述 二.算法描述 三.求解说明 四.参考资料 五.源代码 ...

  2. 基于遗传算法求解TSP问题(Java界面)

    近期为做展示,改写了一个遗传算法求TSP的Java界面版,思路代码和 http://blog.csdn.net/wangqiuyun/article/details/12838903 这篇文章思路是一 ...

  3. Python动态展示遗传算法求解TSP旅行商问题(转载)

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/jiang425776024/articl ...

  4. 遗传算法的C语言实现(二)-----以求解TSP问题为例

    上一次我们使用遗传算法求解了一个较为复杂的多元非线性函数的极值问题,也基本了解了遗传算法的实现基本步骤.这一次,我再以经典的TSP问题为例,更加深入地说明遗传算法中选择.交叉.变异等核心步骤的实现.而 ...

  5. 遗传算法求解旅行商(TSP)问题 -- python

    参考资料: 遗传算法解决TSP旅行商问题(附:Python实现) 遗传算法详解(GA)(个人觉得很形象,很适合初学者) from itertools import permutations impor ...

  6. 基于粒子群算法求解求解TSP问题(JAVA)

    一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...

  7. 模拟退火算法(SA)求解TSP 问题(C语言实现)

    这篇文章是之前写的智能算法(遗传算法(GA).粒子群算法(PSO))的补充.其实代码我老早之前就写完了,今天恰好重新翻到了,就拿出来给大家分享一下,也当是回顾与总结了. 首先介绍一下模拟退火算法(SA ...

  8. 基于贪心算法求解TSP问题(JAVA)

    概述 前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 详细 代码下载:http://www.de ...

  9. 遗传算法解决TSP问题

    1实验环境 实验环境:CPU i5-2450M@2.50GHz,内存6G,windows7 64位操作系统 实现语言:java (JDK1.8) 实验数据:TSPLIB,TSP采样实例库中的att48 ...

随机推荐

  1. widows 2008 同步时间命令

    由于windows2008没有提供类似XP的自动同步功能,因此需要使用windows 2008计划任务来运行一行命令进行同步.   首先查看与想要同步时间的internet时间服务器的时差: w32t ...

  2. springcloud 学习笔记

    ---恢复内容开始--- 1. pom配置 1.1 引入spring boot 依赖 <parent> <groupId>org.springframework.boot< ...

  3. 使用UltraISO刻录自己的音乐CD步骤

    1.文件->新建->音乐光盘映像. 2.在左下方,“本地目录”中,找到音乐所在目录,右下方会出现mp3等音乐文件. 3.在右下方,点击音乐文件,右键选“添加”.音乐文件会出现在右上方窗口里 ...

  4. 【翻译自mos文章】怎么找到OGG Director Server使用的数据库和username?

    APPLIES TO: Management Pack for Oracle GoldenGate - Version: 1.0.0.0 - Release: 1.0 Information in t ...

  5. java栈、堆

    一.栈.堆 几个小概念 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的 ...

  6. arm-linux交叉编译环境搭建

    1.解压交叉编译工具链包 tar jxvf EABI-4.3.3_EmbedSky_20100610.tar.bz2 (笔者将交叉编译工具链包放在”/home ”目录下) 解压后会生成两个目录: [r ...

  7. appium-java-api

    AppiumDriver getAppStrings() 默认系统语言对应的Strings.xml文件内的数据. driver.getAppStrings(String language) 查找某一个 ...

  8. IE8与vs2005冲突 添加MFC类向导错误解决方法—— internet explorer脚本错误

    IE8 与 VS2005 冲突问题解决方法 问题表现为: MFC类向导添加类时,出现“当前页面的脚本发生错误”,进入MFC类向导后上方有一个小黄条“此网站的某个加载项运行失败.请检查"Int ...

  9. Mac 下如何安装pip 和xlwt

    sudo easy_install pip pip install xlwt sudo pip install xlwt sudo pip install requests

  10. Understanding When to use RabbitMQ or Apache Kafka Kafka RabbitMQ 性能对比

    Understanding When to use RabbitMQ or Apache Kafka https://content.pivotal.io/rabbitmq/understanding ...