zoukankan      html  css  js  c++  java
  • 遗传算法求解TSP问题

    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());
        }
    }
  • 相关阅读:
    刘强东:当下正是行业谷底,可卖了两辆车的二手车电商却估值2亿美金 传统商业的价值和经济规律完全适用于互联网 任何一种互联网商业模式,如果不能够降低行业的交易成本,不能够提升行业交易效率的话,那么最后注定会失败的。
    学习一样新东西行而有效的方法 学习捷径 一项由10个步骤组成的学习方法
    侃侃程序员的个人努力与前途问题 程序员到底怎么了
    你觉得你在创业,但其实你可能只是在做小生意而已 制定正确的计划 创业和经营小企业之间的差异
    外贸圈 贸易经 外贸心路 一位成功外贸人的SOHO心得
    总结创业成功的共性 企业成功的必要条件 --投资教父阎焱:创业成功的九九八十一难
    Navicat 12.x for MySQL最新版安装破解教程(附安装包和注册机,全网独家可用
    Xmanager PowerSuite 6企业版详细安装破解教程,解决评估过期问题(附注册机,全网独家可用),非学校/家庭免费版
    UltraEdit等软件详细安装破解教程,附注册机(全网独家可用)
    SpringBoot2.0微信小程序支付多次回调问题
  • 原文地址:https://www.cnblogs.com/Michael2397/p/7630046.html
Copyright © 2011-2022 走看看