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. 【面试 hibernate】【第二篇】hibernate相关问题

    1.hibernate工作原理[说一下你怎么理解的hibernate] hibernate是一个ORM对象关系映射的持久层框架,是对JDBC的轻量级封装. [可以不记,hibernate核心接口] 1 ...

  2. 五步掌握Git的基本开发使用命令

    第一步:设置全局变量: git config --global user.name "gang.li" git config --global user.email "l ...

  3. 转:Twemproxy——针对MemCached与Redis的代理

    转自: http://www.infoq.com/cn/news/2012/12/twemproxy Twemproxy是一个代理服务器,可以通过它减少Memcached或Redis服务器所打开的连接 ...

  4. [POI 2001+2014acm上海邀请赛]Gold Mine/Beam Cannon 线段树+扫描线

    Description  Byteman, one of the most deserving employee of The Goldmine of Byteland, is about to re ...

  5. iOS提交应用至App Store流程及真机调试 一,证书、配置文件

    前言:你要有苹果开发人员账号,我用的是个人账号.其次xcode为xcode 7,因为xcode 7须要 os x 系统 10.11 或更高的版本号, 所以os x 系统也须要 10.11 或更高的版本 ...

  6. Mysql整数运算NULL值处理注意点

    CleverCode近期在导出报表的时候,在整数做减法的时候,发现整数减去null得到是null.这是一个细节问题,希望大家以后注意. 1 表中的数据 total,used都是整形,同意为空. 2 有 ...

  7. TestNG demo

    下载TestNG的归档文件 下载最新版本的TestNG的jar文件,详细请点击访问 http://www.testng.org..在写这篇教程的时候,我下载TestNG中-6.8.jar,并将 tes ...

  8. C语言的一些特殊使用方法————————【Badboy】

    一:特殊的字符串宏 [cpp] #define A(x) T_##x #define B(x) #@x #define C(x) #x 我们如果x=1, 则上面的宏定义会被解释成下面的样子 A(1)- ...

  9. win7 64位安装vs2013 出现'System.AccessViolationException的错误

    用管理员身份运行CMD,输入netsh winsock reset并回车(注意,必须是已管理员身份运行,这个重置LSP连接)

  10. 关闭SVN服务

    关闭TSVNCache.exe进程 在Windows下使用SVN,通常都会安装TortoiseSVN,安装后会有一个TSVNCache.exe的进程驻留内存,这个进程会定时地去扫描Subversion ...