遗传算法求解TSP及其变式

2023-11-05

	刚刚接触遗传算法,主要学习的是以下几位老师的文章(抱拳),链接附上:

https://blog.csdn.net/u010451580/article/details/51178225
https://blog.csdn.net/wangqiuyun/article/details/12838903

写这篇文章主要是系统地整理一下我这几天学到了算法,所以内容不多。

1.遗传算法简介

遗传算法(Genetic Algorithm, GA)起源于对生物系统所进行的计算机模拟研究。它是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法,借鉴了达尔文的进化论和孟德尔的遗传学说。
算法是将初始解构成初始种群,然后不断遗传、进化、变异,最终从中挑选出最优个体,应该算是基于大数据的。
有三种基本算子:选择,交叉,变异,

遗传算法的实施步骤如下(以目标函数求最小为例)。
第一步:初始化 t←0进化代数计数器;T是最大进化代数;随机生成M个个体作为初始群体P(t);
第二步:个体评价 计算P(t)中各个个体的适应度;(即评估个体好坏的一个指标)
第三步:选择运算 将选择算子作用于群体;(类似于物竞天择,适者生存)
第四步:交叉运算 将交叉算子作用于群体;(两个体交叉繁殖出新个体)斜体样式
第五步:变异运算 将变异算子作用于群体,并通过以上运算得到下一代群体P(t + 1);(自身变异形成新个体)
第六步:终止条件判断 t≦T:t← t+1 转到步骤2;t>T:终止 输出解。

常见的选择策略:
最常见的是赌轮选择方法,本质是个体被选中的概率与适应度成正比。这里选择的时候会用到累计概率,即计算出个体的适应度后,求出个体适应度占总适应度的一个比例,如个体1、个体2、个体3的适应度分别为f1,f2,f3,总适应度sumf = f1+f2+f3.则个体1、2、3的累计概率分别为f1/sumf, (f1+f2)/sumf, (f1+f2+f3)/sumf。最后一个数必然为1,则构成一个0-1的轮盘,随机数落在哪个范围,即选择对应个体作为新种群的一员。

那么具体如何选择,如何交叉?且看一下大神整理的:
https://www.cnblogs.com/legend1130/p/5333087.html
常见交叉策略:
https://blog.csdn.net/ztf312/article/details/82793295

其实感觉算法还是要结合一下具体事例(代码)一起看的,刚开始看算法似懂非懂,雾里看花的感觉,还是看了一遍别人写的具体代码才拨云见月。

2.具体应用——TSP问题

TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。
1、
基本思路:
1》初始化:随机生成scale条路径放入oldpopulation,(城市作为编号,编码表示路径。scale为种群的规模,每一条路径为一个个体)
2》算适应度:路径的长度越短,适应度(fitness)最高
3》挑选出适应度最高的路径放入newpopulation,若优于之前的best_tour,则更新best_tour
4》计算种群中个个体的累计概率,用赌轮选择法挑选出下一代放入newpopulation
5》对newpopulation进行交叉
6》对newpopulation进行变异
7》将newpopulation—>oldpopulation,
8》将重复进行2-7

代码附上:(和wangqiuyun博主不同的是我的代码所需数据是自己给的(也可自己文件读写),八个城市的距离矩阵(无向图,所以是对称矩阵)

private int[][] distance =
{{0, 300, 360, 210, 590, 475 , 500, 690},
{300, 0 ,380, 270, 230, 285, 200, 390},
{360, 380, 0 ,510 ,230, 765, 580, 770},
{210, 270 , 510, 0, 470, 265, 450, 640},
{590, 230, 230, 470 ,0, 515 , 260, 450},
{475, 285, 765, 265, 515, 0 ,460, 650},
{500, 200 , 580 , 450 ,260 ,460 ,0 ,190},
{690, 390 ,770, 640 ,450, 650 ,190, 0}}; )


import java.io.BufferedReader;  
import java.io.FileInputStream;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.util.Random;  
 
public class GA {  
  
    private int scale;// 种群规模  
    private int cityNum; // 城市数量,染色体长度  
    private int MAX_GEN; // 运行代数 
    private int start = 0;
    private int end = 7;
  
   private int[][] distance = 
    	    {{0,   300,  360,   210,    590,    475	,   500,	690},
    		{10000,	0	,380,	270,	230,	285,	200,	390},
    		{10000,	380,	0	,510	,230,	765,	580,	770},
    		{10000,	270	, 510,	 0,	    470,	265,	450,	640},
    		{10000,	230,  230,   470	,0,	    515	,   260,	450},
    		{10000,	285,   765,	 265,	515,	0	,460,	650},
    		{10000,	200	,  580	, 450	,260	,460	,0	,190},
    		{10000,	10000	,10000,	10000	,10000,	10000	,10000,	0}}; // 距离矩阵 */ 
    private int bestT;// 最佳出现代数  
    private int bestLength; // 最佳长度  
    private int[] bestTour; // 最佳路径  
  
    // 初始种群,父代种群,行数表示种群规模,一行代表一个个体,即染色体,列表示染色体基因片段  
    private int[][] oldPopulation;  
    private int[][] newPopulation;// 新的种群,子代种群  
    private int[] fitness;// 种群适应度,表示种群中各个个体的适应度  
  
    private float[] Pi;// 种群中各个个体的累计概率  
    private float Pc;// 交叉概率  
    private float Pm;// 变异概率  
    private int t;// 当前代数  
  
    
    private Random random;  
  
    public GA() {  
  
    }  
  
    /** 
     * constructor of GA 
     *  
     * @param s 
     *            种群规模 
     * @param n 
     *            城市数量 
     * @param g 
     *            运行代数 
     * @param c 
     *            交叉率 
     * @param m 
     *            变异率 
     *  
     **/  
    public GA(int s, int n, int g, float c, float m) {  
        scale = s;  
        cityNum = n;  
        MAX_GEN = g;  
        Pc = c;  
        Pm = m;  
    }  
  
    // 给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默  
    @SuppressWarnings("resource")  
    /** 
     * 初始化GA算法类 
     * @param filename 数据文件名,该文件存储所有城市节点坐标数据 
     * @throws IOException 
     */  
    private void init(String filename) throws IOException {  
        // 读取数据  
        /*int[] x;  
        int[] y;  
        String strbuff;  
        BufferedReader data = new BufferedReader(new InputStreamReader(  
                new FileInputStream(filename)));  
        distance = new int[cityNum][cityNum];  
        x = new int[cityNum];  
        y = new int[cityNum];  
        for (int i = 0; i < c ityNum; i++) {  
            // 读取一行数据,数据格式1 6734 1453  
            strbuff = data.readLine();  
            // 字符分割  
            String[] strcol = strbuff.split(" ");  
            x[i] = Integer.valueOf(strcol[1]);// x坐标  
            y[i] = Integer.valueOf(strcol[2]);// y坐标  
        }  
        // 计算距离矩阵  
        // ,针对具体问题,距离计算方法也不一样,此处用的是att48作为案例,它有48个城市,距离计算方法为伪欧氏距离,最优值为10628  
        for (int i = 0; i < cityNum - 1; i++) {  
            distance[i][i] = 0; // 对角线为0  
            for (int j = i + 1; j < cityNum; j++) {  
                double rij = Math  
                        .sqrt(((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j])  
                                * (y[i] - y[j])) / 10.0);  
                // 四舍五入,取整  
                int tij = (int) Math.round(rij);  
                if (tij < rij) {  
                    distance[i][j] = tij + 1;  
                    distance[j][i] = distance[i][j];  
                } else {  
                    distance[i][j] = tij;  
                    distance[j][i] = distance[i][j];  
                }  
            }  
        }  
        distance[cityNum - 1][cityNum - 1] = 0;  */
    			
        bestLength = Integer.MAX_VALUE;  
        bestTour = new int[cityNum + 1];  
        bestT = 0;  
        t = 0;  
  
        newPopulation = new int[scale][cityNum];  
        oldPopulation = new int[scale][cityNum];  
        fitness = new int[scale];  
        Pi = new float[scale];  
  
        random = new Random(System.currentTimeMillis());  
        /* 
         * for(int i=0;i<cityNum;i++) { for(int j=0;j<cityNum;j++) { 
         * System.out.print(distance[i][j]+","); } System.out.println(); } 
         */  
        // 初始化种群  
  
    }  
  
    // 初始化种群  
    void initGroup() {  
        int i, j, k;  
        // Random random = new Random(System.currentTimeMillis());  
        for (k = 0; k < scale; k++)// 种群数  
        {  
            oldPopulation[k][0] = random.nextInt(65535) % cityNum;  
            for (i = 1; i < cityNum;)// 染色体长度  
            {  
                oldPopulation[k][i] = random.nextInt(65535) % cityNum;  
                for (j = 0; j < i; j++) {  
                    if (oldPopulation[k][i] == oldPopulation[k][j]) {  
                        break;  
                    }  
                }  
                if (j == i) {  
                    i++;  
                }  
            }  
        }  
  
        /* 
         * for(i=0;i<scale;i++) { for(j=0;j<cityNum;j++) { 
         * System.out.print(oldPopulation[i][j]+","); } System.out.println(); } 
         */  
    }  
    //返回路径长度
    public int evaluate(int[] chromosome) {  
        // 0123  
        int len = 0;  
        // 染色体,起始城市,城市1,城市2...城市n  
        for (int i = 1; i < cityNum; i++) {  
            len += distance[chromosome[i - 1]][chromosome[i]];  
        }  
        // 城市n,起始城市  
       // len += distance[chromosome[cityNum - 1]][chromosome[0]];  
        return len;  
    }  
  
    // 计算种群中各个个体的累积概率,前提是已经计算出各个个体的适应度fitness[max],作为赌轮选择策略一部分,Pi[max]  
    void countRate() {  
        int k;  
        double sumFitness = 0;// 适应度总和  
  
        double[] tempf = new double[scale];  
  
        for (k = 0; k < scale; k++) {  
            tempf[k] = 10.0 / fitness[k];  //适应度越小,temp越大,即temp与长度成反比
            sumFitness += tempf[k];  
        }  
  
        Pi[0] = (float) (tempf[0] / sumFitness);  
        for (k = 1; k < scale; k++) {  
            Pi[k] = (float) (tempf[k] / sumFitness + Pi[k - 1]);  //累积概率
        }  
  
        /* 
         * for(k=0;k<scale;k++) { System.out.println(fitness[k]+" "+Pi[k]); } 
         */  
    }  
  
    // 挑选某代种群中适应度最高的个体,直接复制到子代中 (即路径长度的值最低) 
    // 前提是已经计算出各个个体的适应度Fitness[max]  
    public void selectBestGh() {  
        int k, i, maxid;  
        int maxevaluation;  
  
        maxid = 0;  
        maxevaluation = fitness[0];  
        for (k = 1; k < scale; k++) {  
            if (maxevaluation > fitness[k]) {  
                maxevaluation = fitness[k];  
                maxid = k;  
            }  
        }  
  
        if (bestLength > maxevaluation) {  
            bestLength = maxevaluation;  
            bestT = t;// 最好的染色体出现的代数;  
            for (i = 0; i < cityNum; i++) {  
                bestTour[i] = oldPopulation[maxid][i];  
            }  
        }  
  
        // System.out.println("代数 " + t + " " + maxevaluation);  
        // 复制染色体,k表示新染色体在种群中的位置,kk表示旧的染色体在种群中的位置  
        copyGh(0, maxid);// 将当代种群中适应度最高的染色体k复制到新种群中,排在第一位0  
    }  
  
    // 复制染色体,k表示新染色体在种群中的位置,kk表示旧的染色体在种群中的位置  
    public void copyGh(int k, int kk) {  
        int i;  
        for (i = 0; i < cityNum; i++) {  
            newPopulation[k][i] = oldPopulation[kk][i];  
        }  
    }  
  
    // 赌轮选择策略挑选  
    public void select() {  
        int k, i, selectId;  
        float ran1;  
        // Random random = new Random(System.currentTimeMillis());  
        for (k = 1; k < scale; k++) {  
        	ran1 = (float) (random.nextInt(65535) % 1000 / 1000.0);  
                // System.out.println("概率"+ran1);  
                // 产生方式  
            for (i = 0; i < scale; i++) {  
            	if (ran1 <= Pi[i]) {  
                        break;  
                }  
            }  
            selectId = i;  
                // System.out.println("选中" + selectId);  
            copyGh(k, selectId);
              
        }  
    }  
  
    //进化函数,正常交叉变异  
    public void evolution() {  
        int k;  
        // 挑选某代种群中适应度最高的个体  
        selectBestGh();  
  
        // 赌轮选择策略挑选scale-1个下一代个体  
        select();  
  
        // Random random = new Random(System.currentTimeMillis());  
        float r;  
  
        // 交叉方法  
        for (k = 0; k < scale; k = k + 2) {  
            r = random.nextFloat();// /产生概率  
            // System.out.println("交叉率..." + r);  
            if (r < Pc) {  
                // System.out.println(k + "与" + k + 1 + "进行交叉...");  
                //OXCross(k, k + 1);// 进行交叉  
                OXCross1(k, k + 1);  
            } else {  
                r = random.nextFloat();// /产生概率  
                // System.out.println("变异率1..." + r);  
                // 变异  
                if (r < Pm) {  
                    // System.out.println(k + "变异...");  
                    OnCVariation(k);  
                }  
                r = random.nextFloat();// /产生概率  
                // System.out.println("变异率2..." + r);  
                // 变异  
                if (r < Pm) {  
                    // System.out.println(k + 1 + "变异...");  
                    OnCVariation(k + 1);  
                }  
            }  
  
        }  
    }  
  
    //进化函数,保留最好染色体不进行交叉变异  
    public void evolution1() {  
        int k;  
        // 挑选某代种群中适应度最高的个体  
        selectBestGh();  
  
        // 赌轮选择策略挑选scale-1个下一代个体  
        select();  
  
        // Random random = new Random(System.currentTimeMillis());  
        float r;  
  
        for (k = 1; k + 1 < scale / 2; k = k + 2) {  
            r = random.nextFloat();// /产生概率  
            if (r < Pc) {  
                //OXCross1(k, k + 1);// 进行交叉  
                OXCross(k,k+1);//进行交叉  
            } else {  
                r = random.nextFloat();// /产生概率  
                // 变异  
                if (r < Pm) {  
                    OnCVariation(k);  
                }  
                r = random.nextFloat();// /产生概率  
                // 变异  
                if (r < Pm) {  
                    OnCVariation(k + 1);  
                }  
            }  
        }  
        if (k == scale / 2 - 1)// 剩最后一个染色体没有交叉L-1  
        {  
            r = random.nextFloat();// /产生概率  
            if (r < Pm) {  
                OnCVariation(k);  
            }  
        }  
  
    }  
  
    // 类OX交叉算子  
    void OXCross(int k1, int k2) {  
        int i, j, k, flag;  
        int ran1, ran2, temp;  
        int[] Gh1 = new int[cityNum];  
        int[] Gh2 = new int[cityNum];  
        // Random random = new Random(System.currentTimeMillis());  
  
        ran1 = random.nextInt(65535) % cityNum;  
        ran2 = random.nextInt(65535) % cityNum;  
        // System.out.println();  
        // System.out.println("-----------------------");  
        // System.out.println("----"+ran1+"----"+ran2);  
  
        while (ran1 == ran2) {  
            ran2 = random.nextInt(65535) % cityNum;  
        }  
  
        if (ran1 > ran2)// 确保ran1<ran2  
        {  
            temp = ran1;  
            ran1 = ran2;  
            ran2 = temp;  
        }  
        // System.out.println();  
        // System.out.println("-----------------------");  
        // System.out.println("----"+ran1+"----"+ran2);  
        // System.out.println("-----------------------");  
        // System.out.println();  
        flag = ran2 - ran1 + 1;// 删除重复基因前染色体长度  
        for (i = 0, j = ran1; i < flag; i++, j++) {  
            Gh1[i] = newPopulation[k2][j];  
            Gh2[i] = newPopulation[k1][j];  
        }  
        // 已近赋值i=ran2-ran1个基因  
  
        for (k = 0, j = flag; j < cityNum;)// 染色体长度  
        {  
            Gh1[j] = newPopulation[k1][k++];  
            for (i = 0; i < flag; i++) {  
                if (Gh1[i] == Gh1[j]) {  
                    break;  
                }  
            }  
            if (i == flag) {  
                j++;  
            }  
        }  
  
        for (k = 0, j = flag; j < cityNum;)// 染色体长度  
        {  
            Gh2[j] = newPopulation[k2][k++];  
            for (i = 0; i < flag; i++) {  
                if (Gh2[i] == Gh2[j]) {  
                    break;  
                }  
            }  
            if (i == flag) {  
                j++;  
            }  
        }  
  
        for (i = 0; i < cityNum; i++) {  
            newPopulation[k1][i] = Gh1[i];// 交叉完毕放回种群  
            newPopulation[k2][i] = Gh2[i];// 交叉完毕放回种群  
        }  
  
        // System.out.println("进行交叉--------------------------");  
        // System.out.println(k1+"交叉后...");  
        // for (i = 0; i < cityNum; i++) {  
        // System.out.print(newPopulation[k1][i] + "-");  
        // }  
        // System.out.println();  
        // System.out.println(k2+"交叉后...");  
        // for (i = 0; i < cityNum; i++) {  
        // System.out.print(newPopulation[k2][i] + "-");  
        // }  
        // System.out.println();  
        // System.out.println("交叉完毕--------------------------");  
    }  
  
    // 交叉算子,相同染色体交叉产生不同子代染色体  
    public void OXCross1(int k1, int k2) {  
        int i, j, k, flag;  
        int ran1, ran2, temp;  
        int[] Gh1 = new int[cityNum];  
        int[] Gh2 = new int[cityNum];  
        // Random random = new Random(System.currentTimeMillis());  
  
        ran1 = random.nextInt(65535) % cityNum;  
        ran2 = random.nextInt(65535) % cityNum;  
        while (ran1 == ran2) {  
            ran2 = random.nextInt(65535) % cityNum;  
        }  
  
        if (ran1 > ran2)// 确保ran1<ran2  
        {  
            temp = ran1;  
            ran1 = ran2;  
            ran2 = temp;  
        }  
  
        // 将染色体1中的第三部分移到染色体2的首部  
        for (i = 0, j = ran2; j < cityNum; i++, j++) {  
            Gh2[i] = newPopulation[k1][j];  
        }  
  
        flag = i;// 染色体2原基因开始位置  
  
        for (k = 0, j = flag; j < cityNum;)// 染色体长度  
        {  
            Gh2[j] = newPopulation[k2][k++];  
            for (i = 0; i < flag; i++) {  
                if (Gh2[i] == Gh2[j]) {  
                    break;  
                }  
            }  
            if (i == flag) {  
                j++;  
            }  
        }  
  
        flag = ran1;  
        for (k = 0, j = 0; k < cityNum;)// 染色体长度  
        {  
            Gh1[j] = newPopulation[k1][k++];  
            for (i = 0; i < flag; i++) {  
                if (newPopulation[k2][i] == Gh1[j]) {  
                    break;  
                }  
            }  
            if (i == flag) {  
                j++;  
            }  
        }  
  
        flag = cityNum - ran1;  
  
        for (i = 0, j = flag; j < cityNum; j++, i++) {  
            Gh1[j] = newPopulation[k2][i];  
        }  
  
        for (i = 0; i < cityNum; i++) {  
            newPopulation[k1][i] = Gh1[i];// 交叉完毕放回种群  
            newPopulation[k2][i] = Gh2[i];// 交叉完毕放回种群  
        }  
    }  
  
    // 多次对换变异算子  
    public void OnCVariation(int k) {  
        int ran1, ran2, temp;  
        int count;// 对换次数  
  
        // Random random = new Random(System.currentTimeMillis());  
        count = random.nextInt(65535) % cityNum;  
  
        for (int i = 0; i < count; i++) {  
  
            ran1 = random.nextInt(65535) % cityNum;  
            ran2 = random.nextInt(65535) % cityNum;  
            while (ran1 == ran2) {  
                ran2 = random.nextInt(65535) % cityNum;  
            }  
            temp = newPopulation[k][ran1];  
            newPopulation[k][ran1] = newPopulation[k][ran2];  
            newPopulation[k][ran2] = temp;  
        }  
  
        /* 
         * for(i=0;i<L;i++) { printf("%d ",newGroup[k][i]); } printf("\n"); 
         */  
    }  
  
    public void solve() {  
        int i;  
        int k;  
  
        // 初始化种群  
        initGroup();  
        // 计算初始化种群适应度,Fitness[max]  
        for (k = 0; k < scale; k++) {  
            fitness[k] = evaluate(oldPopulation[k]); //适应度即路径长度
           // if(oldPopulation[k][0] == start|| oldPopulation[k][7] == end)
            //	fitness[k] = -1;
            // System.out.println(fitness[k]);  
        }  
        // 计算初始化种群中各个个体的累积概率,Pi[max]  
        countRate();  
        System.out.println("初始种群...");  
        for (k = 0; k < scale; k++) {  
            for (i = 0; i < cityNum; i++) {  
                System.out.print(oldPopulation[k][i] + ",");  
            }  
            System.out.println();  
            System.out.println("----" + fitness[k] + " " + Pi[k]);  
        }  
          
        for (t = 0; t < MAX_GEN; t++) {  
            //evolution();  
            evolution1();  
            // 将新种群newGroup复制到旧种群oldGroup中,准备下一代进化  
            for (k = 0; k < scale; k++) {  
                for (i = 0; i < cityNum; i++) {  
                    oldPopulation[k][i] = newPopulation[k][i];  
                }  
            }  
            // 计算种群适应度  
            for (k = 0; k < scale; k++) {  
                fitness[k] = evaluate(oldPopulation[k]);  
               // if(oldPopulation[k][0] == start || oldPopulation[k][7] == end)
                //	fitness[k] =-1;
            }  
            // 计算种群中各个个体的累积概率  
            countRate();  
        }  
  
        System.out.println("最后种群...");  
        for (k = 0; k < scale; k++) {  
            for (i = 0; i < cityNum; i++) {  
                System.out.print(oldPopulation[k][i] + ",");  
            }  
            System.out.println();  
            System.out.println("---" + fitness[k] + " " + Pi[k]);  
        }  
  
        System.out.println("最佳长度出现代数:");  
        System.out.println(bestT);  
        System.out.println("最佳长度");  
        System.out.println(bestLength);  
        System.out.println("最佳路径:");  
        for (i = 0; i < cityNum; i++) {  
            System.out.print(bestTour[i] + ",");  
        }  
  
    }  
  
      
    /** 
     * @param args 
     * @throws IOException 
     */  
 
    public static void main(String[] args) throws IOException {  
        System.out.println("Start....");  
        GA ga = new GA(30, 8, 2000, 0.8f, 0.9f);  
        ga.init("c://data.txt");  
        ga.solve();  
    }  
  
} 

2、TSP变式
如果出发点和终点固定假设城市0位起点,城市7为终点,可将该路线图想象为有向图,所有城市均不能到达城市0,城市7不能不到达所有城市(都设为无穷大),经过迭代后即可求出答案
距离矩阵
private int[][] distance =
{{0, 300, 360, 210, 590, 475 , 500, 690},
{10000, 0 ,380, 270, 230, 285, 200, 390},
{10000, 380, 0 ,510 ,230, 765, 580, 770},
{10000, 270 , 510, 0, 470, 265, 450, 640},
{10000, 230, 230, 470 ,0, 515 , 260, 450},
{10000, 285, 765, 265, 515, 0 ,460, 650},
{10000, 200 , 580 , 450 ,260 ,460 ,0 ,190},
{10000, 10000 ,10000, 10000 ,10000, 10000 ,10000, 0}}; // 距离矩阵 */
其余代码同上

3.有约束条件的遗传算法

TSP问题没有其他的约束条件,但对于求解一个多元函数,可能要求
0<x<100,y >x等等,这时候就需要考虑约束条件。
我看过几篇论文,关于这个问题有修复不可行解法,改变遗传算子法,惩罚函数法,我没有深入研究过。不过我做过一个题,是多约束条件的,用了罚函数来体现违反约束的程度,并对适应度进行相应惩罚,也得出了结果。
罚函数是通过对不可行解的惩罚将约束问题转化为无约束问题,任何对约束的违法都要在目标函数中添加惩罚项。这个未完待续……

暂时掌握,后期更新。若文章有误,还请指正,谢谢!

2019年7月16日 周二

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

遗传算法求解TSP及其变式 的相关文章

  • Python3 + Pymysql + mysql 连接方法

    准备材料 1 host地址 127 0 0 1 2 端口号 3306 3 用户名 root 4 密码 5 数据库名 information persons 6 python3 的pymysql库 正式开始 查询 1 首先导入pymysql包
  • C99和C89

    这是c0conut同学的一份作业 也可以理解为总结 为了保留这份作业 写了博客 我尽量使自己写得简单好懂有趣 C99与C89的亲子关系 就如DOM结构一般 C99与C89之间也充满温情 老父亲C89顾名思义出生于89年 也被称为ANSI C

随机推荐

  • validator 重写方法报错

    javax validation ConstraintDeclarationException HV000151 A method overriding another method must not redefine the parame
  • windows常用命令大全

    作者介绍 作者 小刘在C站 每天分享课堂笔记 一起努力 共赴美好人生 夕阳下 是最美的 绽放 目录 运行框命令 cmd中 Windows运行中 快捷键 运行框命令 shutdown s t 后家秒数 计划关机任务 migwiz Window
  • x-oss-process_OSS中的同理心-重要

    x oss process 我不花很多时间在开放源码项目的整个工作日 和许多晚上 上 我对OSS的使用形成了一种或两种意见 特别是在为项目做贡献时 作为一个使用Github之类的工具的社区 我们已经走了很长一段路 这使得在野外发布OSS项目
  • 什么是区块链?

    什么是区块链 今天给大家讲解我们区块链的第一课 我们要学习区块链 首先我们必须得了解什么是区块链 只有理解了区块链的概念 我们才能入门区块链 接下来 我会从浅入深的带着大家去理解区块链的含义 首先 我们从字面上来理解 区块链 包含着两层含义
  • kvm虚拟化技术

    前言 kvm是一种虚拟化技术 使用 概念 kvm是linux内核的模块 它需要CPU支持 采用硬件辅助虚拟化技术Intel VT AMD V 内存的相关技术如Intel的EPT和AMD的RVI 是底层虚拟化内核模块 检查cpu是否支持虚拟化
  • 大学c语言程序设计题库选择题,黑龙江大学C语言程序设计试题库程序单选.doc

    单选题 46 若输入ab 程序运行结果为 main static char a 2 scanf s a printf c c a 1 a 2 C A a b B a C b D 程序出错 47 若有说明 int a 3 4 0 则下面正确的
  • Hadoop HA集群两个NameNode都是standby或者主NameNode是standby,从NameNode是active的情况集锦

    文章目录 背景 架构 HDFS HA配置 错误原因 解决方案 方案一 方案二 方案三 首先查看自己各参数文件是否配置出错 后记 补充 failover transitionToActive 常用端口号及配置文件 常用端口号 hadoop3
  • 服务器上传图片不显示,网站后台上传图片失败或不显示的原因

    这四年多以来 比尔云做过近百个网站 发现好多网站后台上传图片都会出现一些错误 也不管这个程序是ASP的还是PHP的 对于为什么网站后台上传图片失败 今天比尔云结合自己的经验给大家总结一下 大家以后在搞网站时遇到相应的问题就好解决了 第一件事
  • Fine-tuning Large Enterprise Language Models via Ontological Reasoning

    本文是LLM系列文章 针对 Fine tuning Large Enterprise Language Models via Ontological Reasoning 的翻译 基于本体论推理的大型企业语言模型微调 摘要 1 引言 2 微调
  • 十大图像数据标注工具大合集

    给大家推荐十大标注工具 1 常见的标注方法 人工数据标注 的好处是标注结果比较可靠 自动数据标注 一般都需要二次复核 避免程序错误 外包数据标注 很多时候会面临数据泄密与流失风险 2 人工标注工具 可以分为客户端与WEB端标注工具 推荐使用
  • CUDA 7.5 安装及配置(WIN7 64 英伟达G卡 VS2013)

    第一步 下载cuda 7 5最新版本 https developer nvidia com cuda downloads 第二步 运行安装程序 安装过程中选择自定义 第三步 安装完毕 可以看到系统中多了CUDA PATH和CUDA PATH
  • Python算法--求1-100之间所有的偶数和奇数

    i 1 sum1 0 sum2 0 while i lt 100 if i 2 0 sum1 i else sum2 i i 1 print 1 100之间偶数和为 d sum1 print 1 100之间奇数和为 d sum2
  • MySQL递归查询

    在平常开发过程中 递归查询随处可见 话不多说 本人在项目中遇到的是编码和父级编码 需要逐渐查询 1 表结构 2 SQL SELECT id SELECT REPLACE GROUP CONCAT code FROM ddm file dir
  • windows下网卡绑定多个IP地址的方法

    在Windows下 尤其是Windows的服务器 有时候需要在一张网卡上绑定多个IP地址 有两种方法可以完成 一是使用控制面板可视化配置 进入控制面板 网络设置 Network and Internet 网络和共享中心 Network an
  • Deep Learning for Anomaly Detection: A Review

    本文是对 Deep Learning for Anomaly Detection A Review 的翻译 深度学习进行异常检测 综述 摘要 1 引言 2 异常检测 问题复杂性和挑战 2 1 主要问题复杂性 2 2 深度异常检测面临的主要挑
  • 产品经理实战--抖音

    目录 抖音 短视频发展历程 短视频概念 短视频在马斯洛理论上的应用 短视频行业发展历程 规划设计一款产品的思路和流程 报名学习 后台产品 前端 包含app 顶部导航 侧边导航 流程图 设计一款APP的思路和流程 抖音 我规划设计APP的思路
  • cvc-complex-type.2.4.a: 发现了以元素 ‘base-extension‘ 开头的无效内容。(解决方案的最全整理)

    记录一下 新电脑安装新版的Android Studio 小蜜蜂版本 导入那些gradle还是5 1 1 distributionUrl https services gradle org distributions gradle 5 1 1
  • Java字符串不相同但HashCode相同的例子(算法)

    相关文章 为什么重写equals方法时必须重写hashcode方法 Java字符串不相同但HashCode相同的例子 算法 Java字符串不相同但HashCode相同的例子 public static void main String ar
  • 符号 ?. 是什么

    在修改问题的时候 看到别人的代码是这样的 如图 不太懂 是干嘛的 于是去查关键字 js 发现这是ES2020 ES11 新增的 可选链操作符 可选链操作符 允许读取位于连接对象链深处的属性的值 而不必明确验证链中的每个引用是否有效 操作符的
  • 遗传算法求解TSP及其变式

    刚刚接触遗传算法 主要学习的是以下几位老师的文章 抱拳 链接附上 https blog csdn net u010451580 article details 51178225 https blog csdn net wangqiuyun