遗传算法 与旅行商问题

用遗传算法解决旅行商问题

genetic algorithm to solve TSP problem

参考连接:Genetic algorithm – Wikipedia

                    Travellingsalesman problem – Wikipedia

                    Travelling-Salesman–a-Genetic-Algorithm

旅行商问题:

给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。它是组合优化中的一个NP困难问题,在运筹学和理论计算机科学中非常重要。

 

遗传算法: 

遗传算法通常实现方式为一种计算机模拟。对于一个最优化问题,一定数量的候选解(称为个体)可抽象表示为染色体,使种群向更好的解进化。传统上,解用二进制表示(即0和1的串),但也可以用其他表示方法。进化从完全随机个体的种群开始,之后一代一代发生。在每一代中评价整个种群的适应度,从当前种群中随机地选择多个个体(基于它们的适应度),通过自然选择和突变产生新的生命种群,该种群在算法的下一次迭代中成为当前种群。


流程与步骤
    第一步:初始化 t←0进化代数计数器;T是最大进化代数;随机生成M个个体作为初始    群体P(t);
    第二步:个体评价计算P(t)中各个个体的适应度;
    第三步:选择运算将选择算子作用于群体;
    第四步:交叉运算将交叉算子作用于群体;
    第五步:变异运算将变异算子作用于群体,并通过以上运算得到下一代群体P(t + 1);
    第六步:终止条件判断  t≦T:t← t+1 转到步骤2;t>T:终止 输出解。

《遗传算法 与旅行商问题》

基本上可以归结为随机取种群中元素然后两两交配生成下一代,其中可能存在变异,每次通过估价函数来淘汰调一部分,这样迭代。终止条件可以是种群估价可接受或者自己设定迭代次数.

 

 

现在假定问题中的城市是在二维平面上的点,两城市距离为两点的直线距离。

《遗传算法 与旅行商问题》

存储城市信息类City

//通过(x,y)表示一个城市
public class City {
    int x;
    int y;
    
    // 生成随机的城市(x,y)
    public City(){
        this.x = (int)(Math.random()*200);
        this.y = (int)(Math.random()*200);
    }
    
    // 生成城市
    public City(int x, int y){
        this.x = x;
        this.y = y;
    }
    
    
    public int getX(){
        return this.x;
    }
    
    
    public int getY(){
        return this.y;
    }
    
    // 从本城市(this)到城市city的距离
    public double distanceTo(City city){
        int xDistance = Math.abs(getX() - city.getX());
        int yDistance = Math.abs(getY() - city.getY());
        double distance = Math.sqrt( (xDistance*xDistance) + (yDistance*yDistance) );
        
        return distance;
    }
    
    @Override
    public String toString(){
        return getX()+", "+getY();
    }
}

存储所有的城市——全局变量TourManger类

//全局变量list 存储所有的城市 
public class TourManager {

   
    private static ArrayList destinationCities = new ArrayList<City>();

    
    public static void addCity(City city) {
        destinationCities.add(city);
    }
    
    
    public static City getCity(int index){
        return (City)destinationCities.get(index);
    }
    
    
    public static int numberOfCities(){
        return destinationCities.size();
    }
}

处理旅游路径信息类Tour

//旅游的路径类
public class Tour{

    // 用list存储city路径
    private ArrayList tour = new ArrayList<City>();
    // fitness=1/distance
    private double fitness = 0;
    private int distance = 0;
    // 生成一个空路径
    public Tour(){
        for (int i = 0; i < TourManager.numberOfCities(); i++) {
            tour.add(null);
        }
    }
    
    public Tour(ArrayList tour){
        this.tour = tour;
    }

    // 随机生成一个个体
    public void generateIndividual() {
        for (int cityIndex = 0; cityIndex < TourManager.numberOfCities(); cityIndex++) {
          setCity(cityIndex, TourManager.getCity(cityIndex));
        }
        //随机打乱顺序
        Collections.shuffle(tour);
    }

    // 返回路径的tourPosition 元素
    public City getCity(int tourPosition) {
        return (City)tour.get(tourPosition);
    }

    // 设置路径的turPositio元素
    public void setCity(int tourPosition, City city) {
        tour.set(tourPosition, city);
        // If the tours been altered we need to reset the fitness and distance
        fitness = 0;
        distance = 0;
    }
    
    // 获得路径的估价
    public double getFitness() {
        if (fitness == 0) {
            fitness = 1/(double)getDistance();
        }
        return fitness;
    }
    
    // 返回路径总代价
    public int getDistance(){
        if (distance == 0) {
            int tourDistance = 0;
            // 遍历路径
            for (int cityIndex=0; cityIndex < tourSize(); cityIndex++) {
                // 出发城市
                City fromCity = getCity(cityIndex);
                // 目的城市
                City destinationCity;
                // 如果出发城市是路径的最后一个则返回起点
                //否则去往路径的后一个城市
                if(cityIndex+1 < tourSize()){
                    destinationCity = getCity(cityIndex+1);
                }
                else{
                    destinationCity = getCity(0);
                }
                
                tourDistance += fromCity.distanceTo(destinationCity);
            }
            distance = tourDistance;
        }
        return distance;
    }

    // 路径中城市的个数
    public int tourSize() {
        return tour.size();
    }
    
    // 路径是否含有该城市
    public boolean containsCity(City city){
        return tour.contains(city);
    }
    
    @Override
    public String toString() {
        String geneString = "|";
        for (int i = 0; i < tourSize(); i++) {
            geneString += getCity(i)+"|";
        }
        return geneString;
    }
}

存储一组旅游路径—–种群类Population

//路径的种群 Population of tour
public class Population {

   
    Tour[] tours;

    public Population(int populationSize, boolean initialise) {
        tours = new Tour[populationSize];
        // 如果需要initialise 为true 初始化 Population
        if (initialise) {
            for (int i = 0; i < populationSize(); i++) {
                Tour newTour = new Tour();
                newTour.generateIndividual();
                saveTour(i, newTour);
            }
        }
    }
    
    
    public void saveTour(int index, Tour tour) {
        tours[index] = tour;
    }
    
    
    public Tour getTour(int index) {
        return tours[index];
    }

    // 返回最优路径
    public Tour getFittest() {
        Tour fittest = tours[0];
        for (int i = 1; i < populationSize(); i++) {
            if (fittest.getFitness() <= getTour(i).getFitness()) {
                fittest = getTour(i);
            }
        }
        return fittest;
    }

    public int populationSize() {
        return tours.length;
    }
}

遗传算法(genetic algorithm)实现类——GA

//genetic algorithm
public class GA{
    private static final double mutationRate=0.015;
    private static final int tournemetSize=5;

    //生成下一代
    public static Population evolvePopulation(Population pop){
        Population nextPopulation=new Population(pop.populationSize(),false);

        //保存本代最优
        nextPopulation.saveTour(0,pop.getFittest());
        //交叉产生下一代
        for(int i=1;i<nextPopulation.populationSize();i++){
            //选取父辈
            Tour parent1 = tournamentSeletction(pop);
            Tour parent2 = tournamentSeletction(pop);
            //交叉产生下一代
            Tour child= crossover(parent1,parent2);
            nextPopulation.addTour(child);
        }
        //变异
        for(int i=1;i<nextPopulation;i++){
            mutate(nextPopulation.getTour(i));
        }
        return nextPopulation;

    }
    //交叉产生下一代
    public static Tour crossover(Tour parent1, Tour parent2){
        Tour child=new Tour();

        int startPos=(int)(Math.random()*parent1.tourSize());
        int endPos=(int)(Math.random()*parent2.tourSize());
        if(startPos<endPos) {int tmp=startPos; startPos=endPos;endPos=tmp;}

        //从parent1选取元素传递给下一代
        for(int i=0;i<child.tourSize();i++)
            if(i>startPos&&i<endPos) child.setCity(i,parent1.getCity(i));
        //从parent2中选取元素传递给下一代
        for(int i=0;i<parent2.tourSize();i++)
            if(!child.containsCity(parent2.get(i)))
                for(int j=0;j<child.tourSize();j++)
                    if(child.getCity(j)==null){
                        child.setCity(j,parent2.getCity(i));
                        break;
                    }
        return child;
    }

    //随机生成数字判断是否需要变异
    //通过交换路径中的两个元素变异
    public static void mutate(Tour tour){
        for(int tourPos1=0; tourPos1< tour.tourSize(); tourPos1++)
            if(Math.random()<mutationRate){
                int tourPos2 = (int) (tour.tourSize() * Math.random());
                City city1 = tour.getCity(tourPos1);
                City city2 = tour.getCity(tourPos2);
                tour.setCity(tourPos2, city1);
                tour.setCity(tourPos1, city2);
            }
    }
    //选取若干各路径Tour选出最优的
    private static Tour tournamentSeletction(Population pop){
        Population tournament = new Population(tournamentSize, false);

        for (int i = 0; i < tournamentSize; i++) {
            int randomId = (int) (Math.random() * pop.populationSize());
            tournament.saveTour(i, pop.getTour(randomId));
        }

        Tour fittest = tournament.getFittest();
        return fittest;
    }
}

测试类TSP_GA:

public class TSP_GA {

    public static void main(String[] args) {

        
        City city = new City(60, 200);
        TourManager.addCity(city);
        City city2 = new City(180, 200);
        TourManager.addCity(city2);
        City city3 = new City(80, 180);
        TourManager.addCity(city3);
        City city4 = new City(140, 180);
        TourManager.addCity(city4);
        City city5 = new City(20, 160);
        TourManager.addCity(city5);
        City city6 = new City(100, 160);
        TourManager.addCity(city6);
        City city7 = new City(200, 160);
        TourManager.addCity(city7);
        City city8 = new City(140, 140);
        TourManager.addCity(city8);
        City city9 = new City(40, 120);
        TourManager.addCity(city9);
        City city10 = new City(100, 120);
        TourManager.addCity(city10);
        City city11 = new City(180, 100);
        TourManager.addCity(city11);
        City city12 = new City(60, 80);
        TourManager.addCity(city12);
        City city13 = new City(120, 80);
        TourManager.addCity(city13);
        City city14 = new City(180, 60);
        TourManager.addCity(city14);
        City city15 = new City(20, 40);
        TourManager.addCity(city15);
        City city16 = new City(100, 40);
        TourManager.addCity(city16);
        City city17 = new City(200, 40);
        TourManager.addCity(city17);
        City city18 = new City(20, 20);
        TourManager.addCity(city18);
        City city19 = new City(60, 20);
        TourManager.addCity(city19);
        City city20 = new City(160, 20);
        TourManager.addCity(city20);

        Population pop = new Population(50, true);
        System.out.println("Initial distance: " + pop.getFittest().getDistance());

        
        pop = GA.evolvePopulation(pop);
        for (int i = 0; i < 100; i++) {
            pop = GA.evolvePopulation(pop);
        }

        
        System.out.println("Finished");
        System.out.println("Final distance: " + pop.getFittest().getDistance());
        System.out.println("Solution:");
        System.out.println(pop.getFittest());
    }
}

运行结果:

《遗传算法 与旅行商问题》

    原文作者:遗传算法
    原文地址: https://blog.csdn.net/emoheithree/article/details/72639502
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞