文章目录

  • 代码
    • Genome基因类
    • GeneticAlgorithm_TSP遗传算法类
  • 运行结果

代码

Genome基因类

import lombok.Data;
import lombok.NoArgsConstructor;/*** @Author:WSKH* @ClassName:Genome* @ClassType:* @Description:* @Date:2022/6/4/12:55* @Email:1187560563@qq.com* @Blog:https://blog.csdn.net/weixin_51545953?type=blog*/
@Data
@NoArgsConstructor
public class Genome {// 距离矩阵public static double[][] dist;// 基因序列private int[] genomeArray;// 适应度函数值private double fitness;// 序列对应的路径长度private double pathLen;// 构造函数public Genome(int[] genomeArray) {this.genomeArray = genomeArray.clone();updateFitnessAndPathLen();}// 获取适应值和路径长度public void updateFitnessAndPathLen(){pathLen = Genome.getPathLen(genomeArray);fitness = 10000d/pathLen;}// 求路程长度public static double getPathLen(int[] path) {double pathLen = 0.0;for (int i = 1; i < path.length; i++) {// 起点到终点途径路程累加pathLen += dist[path[i - 1]][path[i]];}// 然后再加上返回起点的路程pathLen += dist[path[0]][path[path.length - 1]];return pathLen;}}

GeneticAlgorithm_TSP遗传算法类

import java.io.IOException;
import java.io.Serializable;
import java.util.*;/*
**  Create by: 王孙康宏Date:2021-08-04Time:9:07
*/
public class GeneticAlgorithm_TSP implements Serializable {// 城市坐标集合 <[x,y]>List<double[]> locationList;// 距离矩阵double[][] dist;// 城市数量int cityNum;// 放置所有的种群基因信息private List<Genome> population = new ArrayList<>();// 新一代的种群基因信息private List<Genome> newPopulation = new ArrayList<>();// 种群数量信息private int popSize = 100;// 种群总的适应度数值private double totalFitness = 0;// 最好的适应度的对应的染色体(基因序列、路径序列)private Genome bestGenome;// 基因突变概率private double mutationRate = 0.4;// 基因交叉概率private double crossoverRate = 0.98;// 遗传的代数(第几代)private int t = 0;// 变异对换次数private double variationExchangeCount = 1;// 遗传最大的迭代次数private int MAX_GEN = 200000;// 复制最优解的次数(选择种群的最优个体,然后复制几次,将最优个体复制多个,存到新的集合中)int cloneNumOfBestIndividual = 3;// 最佳迭代数private int bestT = 0;// 随机函数对象public Random random;// 各个个体的累积概率double[] probabilitys;public GeneticAlgorithm_TSP(List<double[]> locationList) {this.locationList = locationList;}public void solve() throws IOException, ClassNotFoundException {initVar();solver();}public void solver() throws IOException, ClassNotFoundException {while (t < MAX_GEN) {popSize = population.size();// 基因进化evolution();// 更新种群population = copyGenomeList(newPopulation);t++;}// 输出结果System.out.println("最佳迭代次数:" + bestT);System.out.println("最短路程为:" + bestGenome.getPathLen());int[] bestPath = new int[cityNum + 1];System.arraycopy(bestGenome.getGenomeArray(), 0, bestPath, 0, bestGenome.getGenomeArray().length);bestPath[cityNum] = bestPath[0];System.out.println("最佳路径为:" + Arrays.toString(bestPath));}// 进化函数// 进化函数,正常交叉变异public void evolution() {//更新累积概率和总适应度updateProbabilityAndTotalFitness();// 挑选某代种群中适应度最高的个体HashSet<Integer> actionIndex = selectBestGenomeAndJoinNext();// 赌轮选择策略对剩下的scale-1个个体进行随机的交叉,变异while (newPopulation.size() < population.size()) {double r = random.nextDouble();for (int j = 0; j < probabilitys.length; j++) {if (r <= probabilitys[j]) {newPopulation.add(population.get(j));break;}}}// 交叉if (random.nextDouble() <= crossoverRate) {int r = random.nextInt(popSize);int k = random.nextInt(popSize);while (r == k){r = random.nextInt(popSize);}cross(k, r);}for (int i = 0; i < population.size(); i++) {// 变异if (random.nextDouble() <= mutationRate) {variation(i);}}}// 单点映射交叉private void cross(int k1, int k2) {// 获取要交叉的两个基因int[] genomeArray1 = newPopulation.get(k1).getGenomeArray();int[] genomeArray2 = newPopulation.get(k2).getGenomeArray();// 找到交叉位置int crossIndex = random.nextInt(cityNum);// 获取交叉片段for (int i = 0; i <= crossIndex; i++) {int temp = genomeArray1[i];genomeArray1[i] = genomeArray2[i];genomeArray2[i] = temp;}// 找到重复基因HashSet<Integer> set = new HashSet<>();// <index,value>HashMap<Integer, Integer> repeatMap = new HashMap<>();for (int i = 0; i < genomeArray1.length; i++) {if (!set.add(genomeArray1[i])) {repeatMap.put(i, genomeArray1[i]);}}set.clear();for (int i = 0; i < genomeArray2.length; i++) {if (!set.add(genomeArray2[i])) {for (int key : repeatMap.keySet()) {genomeArray1[key] = genomeArray2[i];genomeArray2[i] = repeatMap.get(key);repeatMap.remove(key);break;}}}// 交叉完毕,将基因放回个体,再将个体放回种群,并更新他们的适应值和路径长度newPopulation.get(k1).setGenomeArray(genomeArray1);newPopulation.get(k1).updateFitnessAndPathLen();newPopulation.get(k2).setGenomeArray(genomeArray2);newPopulation.get(k2).updateFitnessAndPathLen();}public void cross2(int k1, int k2) {// 获取要交叉的两个基因int[] genomeArray1 = newPopulation.get(k1).getGenomeArray();int[] genomeArray2 = newPopulation.get(k2).getGenomeArray();//使用LinkedHashSet存储元素,方便替换元素时,对元素进行删减LinkedHashSet<Integer> hashSetI = new LinkedHashSet<>();LinkedHashSet<Integer> hashSetJ = new LinkedHashSet<>();for (int k = 0; k < this.cityNum; k++) {hashSetI.add(genomeArray1[k]);hashSetJ.add(genomeArray2[k]);}//开始交换的位置,一直交换到尾部,即单点交叉(begin至少要从1开始,否则没有意义)int begin = random.nextInt(this.cityNum - 1) + 1;for (int k = begin; k < this.cityNum; k++) {//交换两个基因的对应位置int temp = genomeArray1[k];genomeArray1[k] = genomeArray2[k];genomeArray2[k] = temp;//删除对应的元素,该元素已经在k位置了hashSetI.remove(genomeArray1[k]);hashSetJ.remove(genomeArray2[k]);}//重新填充非交叉区域的元素begin = 0;for (Integer element : hashSetI) {genomeArray1[begin++] = element;}begin = 0;for (Integer element : hashSetJ) {genomeArray2[begin++] = element;}// 交叉完毕,将基因放回个体,再将个体放回种群,并更新他们的适应值和路径长度newPopulation.get(k1).setGenomeArray(genomeArray1);newPopulation.get(k1).updateFitnessAndPathLen();newPopulation.get(k2).setGenomeArray(genomeArray2);newPopulation.get(k2).updateFitnessAndPathLen();}// 变异(多次对换)private void variation(int k) {Genome genome = newPopulation.get(k);int[] genomeArray = genome.getGenomeArray();for (int i = 0; i < variationExchangeCount; i++) {int r1 = random.nextInt(cityNum);int r2 = random.nextInt(cityNum);while (r1 == r2) {r1 = random.nextInt(cityNum);r2 = random.nextInt(cityNum);}//交换int temp = genomeArray[r1];genomeArray[r1] = genomeArray[r2];genomeArray[r2] = temp;}//将变异后的基因序列放回个体genome.setGenomeArray(genomeArray);// 更新基因的适应值和路程长度genome.updateFitnessAndPathLen();//将变异后的个体放回种群newPopulation.set(k, genome);}//初始化变量public void initVar() {this.cityNum = locationList.size();this.population = new ArrayList<>();random = new Random(System.currentTimeMillis());//初始化距离矩阵dist = new double[cityNum][cityNum];for (int i = 0; i < cityNum; i++) {for (int j = i; j < cityNum; j++) {if (i != j) {dist[i][j] = getDistance(locationList.get(i), locationList.get(j));dist[j][i] = dist[i][j];}}}Genome.dist = dist;//初始化种群信息List<Integer> path = new ArrayList<>();for (int i = 0; i < cityNum; i++) {path.add(i);}for (int i = 0; i < popSize; i++) {Collections.shuffle(path);int[] initPath = new int[cityNum];for (int j = 0; j < path.size(); j++) {initPath[j] = path.get(j);}Genome genome = new Genome(initPath.clone());population.add(genome);}bestGenome = copyGenome(population.get(0));for (int i = 1; i < popSize; i++) {Genome genome = population.get(i);if (bestGenome.getFitness() < genome.getFitness()) {bestGenome = copyGenome(genome);}}System.out.println("初始解为:" + bestGenome.getPathLen());}// 挑选种群中适应度最大的个体基因直接加入下一代种群public HashSet<Integer> selectBestGenomeAndJoinNext() {newPopulation = new ArrayList<>();HashSet<Integer> actionIndex = new HashSet<>();Genome tempBest = population.get(0);int maxIndex = 0;for (int i = 1; i < population.size(); i++) {if (population.get(i).getFitness() > tempBest.getFitness()) {tempBest = population.get(i);maxIndex = i;}}actionIndex.add(maxIndex);if (tempBest.getFitness() > bestGenome.getFitness()) {bestGenome = copyGenome(tempBest);bestT = t;
//            System.out.println("当前代数:" + t + " : " + bestGenome.getPathLen());}for (int i = 0; i < cloneNumOfBestIndividual; i++) {newPopulation.add(copyGenome(tempBest));}return actionIndex;}// 更新各个个体的累积概率和种群总适应度public void updateProbabilityAndTotalFitness() {probabilitys = new double[population.size()];totalFitness = 0;for (Genome genome : population) {totalFitness += genome.getFitness();}double rate = 0.0;for (int i = 0; i < population.size(); i++) {rate += (population.get(i).getFitness() / totalFitness);probabilitys[i] = rate;}}// 计算两点之间的距离(使用伪欧氏距离,可以减少计算量)private double getDistance(double[] place1, double[] place2) {// 伪欧氏距离在根号内除以了一个10return Math.sqrt((Math.pow(place1[0] - place2[0], 2) + Math.pow(place1[1] - place2[1], 2)) / 10.0);
//        return Math.sqrt((Math.pow(place1[0] - place2[0], 2) + Math.pow(place1[1] - place2[1], 2)));}// 拷贝单个基因public Genome copyGenome(Genome genome) {Genome copy = new Genome();copy.setGenomeArray(genome.getGenomeArray().clone());copy.setFitness(genome.getFitness());copy.setPathLen(genome.getPathLen());return copy;}// 拷贝基因集合public List<Genome> copyGenomeList(List<Genome> genomeList) {List<Genome> copyList = new ArrayList<>();for (Genome genome : genomeList) {copyList.add(copyGenome(genome));}return copyList;}}

运行结果

遗传算法求解tsp问题:48个城市...
初始解为:39492.9415375181
最佳迭代次数:18085
最短路程为(伪欧氏距离):11716.839185306864
最佳路径为:[37, 0, 7, 8, 39, 14, 32, 11, 10, 22, 40, 15, 21, 2, 33, 13, 12, 24, 4, 47, 28, 1, 3, 25, 41, 9, 34, 44, 23, 31, 38, 20, 46, 19, 45, 35, 6, 5, 36, 18, 16, 42, 26, 29, 27, 17, 43, 30, 37]
求解用时:3.007 s
-------------------------------------------------------------------------
遗传算法求解tsp问题:48个城市...
初始解为:126129.17281692004
最佳迭代次数:94162
最短路程为(欧氏距离):37319.47142582528
最佳路径为:[21, 15, 40, 33, 2, 13, 24, 4, 28, 1, 25, 3, 34, 44, 9, 23, 41, 47, 38, 31, 20, 46, 22, 12, 10, 11, 19, 32, 45, 29, 26, 18, 36, 16, 42, 5, 35, 17, 27, 6, 43, 30, 37, 14, 39, 8, 7, 0, 21]
求解用时:3.044 s
-------------------------------------------------------------------------

补充:以上使用的是tsplib上的数据att48,这是一个对称TSP问题,城市规模为48,其最优值为10628(取整的伪欧氏距离)。tsplib地址:http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/

【运筹优化】GA遗传算法求解TSP问题(Java实现)相关推荐

  1. 基于遗传算法求解TSP问题(JAVA)

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

  2. 局部搜索、模拟退火和遗传算法求解TSP问题

    模拟退火和遗传算法求解TSP问题 源代码传送门:GITHUB 数据传送门:TSPLIB 文章目录 模拟退火和遗传算法求解TSP问题 摘要 1 导言 1.1 问题重述 1.2 TSP问题选择 1.3 思 ...

  3. 基于遗传算法求解TSP问题(旅游路径规划,Python实现,超详细,可视化,结果分析)

    ps:作者是很用心写的,如果觉得不错,请给作者一点鼓励噢!(点赞收藏评论噢) 基于遗传算法求解TSP问题 摘要 巡回旅行商问题(TSP)是组合优化中的经典问题.常见的TSP问题求解算法例如穷举法.贪心 ...

  4. 【老生谈算法】matlab实现遗传算法求解TSP问题——TSP问题

    遗传算法求解TSP问题MATLAB实现 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]遗传算法求解TSP问题MATLAB实现 ...

  5. 人工智能导论——遗传算法求解TSP问题实验

    一.实验目的: 熟悉和掌握遗传算法的原理.流程和编码策略,并利用遗传算法求解组合优化问题,理解求解TSP问题的流程并测试主要参数对结果的影响. 二.实验原理: 旅行商问题,即TSP问题(Traveli ...

  6. 【建模算法】基于遗传算法求解TSP问题(matlab求解)

    [建模算法]基于遗传算法求解TSP问题(matlab求解) TSP (traveling salesman problem,旅行商问题)是典型的NP完全问题,即其最坏情况下的时间复杂度随着问题规模的增 ...

  7. 【Matlab】 遗传算法求解TSP问题

    [Matlab] 遗传算法求解TSP问题 文章目录 [Matlab] 遗传算法求解TSP问题 前言 一.问题描述 二.实验设计 1.问题案例 2.读入数据 3.适应度计算 4. 选择子代 5. 结果输 ...

  8. 模拟退火算法 java_转 | 模拟退火算法(SA)和迭代局部搜索(ILS)求解TSP的Java代码分享...

    以下文章来源于数据魔术师 ,作者周航 前言 大家好呀!我们你们好久不见的...咳咳,初次见面的小编! 之前重新整理了ILS的代码,有人留言问能不能提供java版. 正好最近在学启发式算法和java,为 ...

  9. 【运筹优化】ACO蚁群算法求解TSP问题(Java实现)

    文章目录 代码 Ant蚂蚁类 AntColonyOptimization_TSP蚁群算法类 运行结果 代码 Ant蚂蚁类 import lombok.Data;import java.util.Arr ...

最新文章

  1. docker load 出错 open /var/lib/docker/tmp/docker-import-837327978/bin/json: no such file or directory
  2. SAP MM 如何知道移动类型的字段选择和会计科目的字段选择是否不一致?
  3. 与癌症作战的 12 家 AI 公司,八仙过海各显神通
  4. 接口练习题(书信接口)
  5. linux下静默安装oracle10g,CentOS下远程静默安装Oracle10g笔记
  6. 广播IP转型报告:远程制作持续崛起
  7. java创建子类对象的步骤_一顿Spring骚操作:我敢说没有人比我更懂Java对象的创建!
  8. java版本号分段比较_Java实现比较版本号
  9. 企业要搞数字化转型,是用一整套ERP,还是各搞各的数据系统?
  10. Java 9 中的 9 个新特性
  11. 老婆生病了,后果很严重!
  12. 2017年最新(4月20日)手机号码归属地数据库分享
  13. 怎么选择boost升压电路的电感?只要三个公式
  14. 互联网晚报 | 06月03日 星期五 | 步步高回应“即将倒闭”传闻、爱彼迎启动房东/房源迁移计划;抖音宣布与中超联赛达成合作...
  15. Hadoop大数据基础知识点总结--持续更新
  16. 从VIVO到华为,让人目瞪口呆的“未来SMT智能工厂”亮相
  17. 告警流量分析:Cobalt Strike(默认实验文)
  18. 华为手机备份的通讯录是什么文件_华为手机通讯录如何备份?
  19. Zookeeper-开源客户端 之 Curator
  20. BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]

热门文章

  1. shell从文件中根据key获取value
  2. 方正飞越 A600硬改BIOS激活win7的工具与方法。
  3. python和django的目录遍历漏洞(任意文件读取)
  4. Android界面设计5--管理系统UI
  5. Docker基础(一)
  6. 抓取在线书店信息:从在线书店获取图书信息及价格
  7. php分布式微服务开发_php| php 微服务之旅: devops
  8. 电脑内部声音怎么录制 Mac在线录制音频
  9. c语言产生随机数停滞,C语言产生随机数,个人理解
  10. 通过openssl学习ssl证书。