Solving tsp problem by genetic algorithm

Source: Internet
Author: User
Tags sprintf

Genetic algorithm is a kind of heuristic search, which belongs to evolutionary algorithm. It was originally designed according to Nature's natural choice of species and genetic laws. It simulates the natural selection, heredity and mutation of nature species, and improves the genes of a population.

The genetic algorithm needs to set parameters such as crossover probability, mutation probability and iteration number, and the convergence of the algorithm is greatly influenced by its parameter setting.
In the genetic algorithm, each candidate solution is considered as an individual, and the set of individual composition is regarded as a population. The genetic algorithm converts each solution into 0-1 strings by binary encoding each solution, where each bit is called a gene. The phenotype of individuals with different combinations of genes is also different. It starts from an initial population and finally obtains the approximate optimal solution through n iterations. During each iteration, he first calculates the fitness of each individual in the initial population and then operates on the initial population using selection operators, genetic operators, and mutation operators. Each operator operation is not a fixed process, but a certain probability of operation. This ensures that the search space of the algorithm can cover the entire solution space and can also strip out the local optimal solution.


There are two kinds of termination conditions, one is that the current optimal solution does not change after continuous w iteration, where w is the threshold value based on experience, usually related to the size of the problem, and the other is that when the algorithm iterates to a certain number of times, it terminates.

The coding of TSP problem solution

Coding is the first problem to be solved when applying genetic algorithm, and it is also a key step of designing genetic algorithm. Besides determining the individual chromosome arrangement, the coding method also determines the decoding method of the individual from the genotype transformation of the search space to the phenotype of the solution space. The coding method also affects the operation methods of the crossover operator, mutation operator and other genetic operators. Thus, the coding method largely determines how to carry out the genetic evolution of the population and the efficiency of the genetic evolutionary operation.

Genetic algorithms are encoded in a number of ways, such as binary encoding, floating-point encoding, and symbol encoding. Choosing the appropriate coding method for different problems can help solve the problem. Based on binary coding for TSP, we cannot guarantee that the solution after the cross-mutation transformation satisfies the test instructions, so we discard this method. The method of coding based on floating-point number is usually used to solve the approximate optimal function value of continuous function, which is not suitable for discrete tsp problem. In the TSP problem, each solution is a sequence of paths consisting of city serial numbers, also known as individuals in the algorithm. Based on the TSP problem, we choose the method of symbol encoding. For example: There are 4 cities, the city serial number is: 0,1,2,3. It is assumed that the shortest route to the city is 0, followed by the city of 0. Then 0-1-2-3-0 is the best solution for the TSP problem in these 4 cities, also known as an individual. A single city ordinal in a path sequence, such as 2, is called a gene of an individual. Usually the optimal solution path is only one, but the path sequence is more than one, such as 1-2-3-0-1, they are only different starting point.

Degree of fitness calculation

In nature, according to genetics, an individual with a higher degree of fitness has the opportunity to be chosen, thus preserving its genes. Therefore, in the design process of genetic algorithm, it is necessary to have positive feedback selection strategy for the degree of adaptability. You need to consider ways to measure each individual's fitness before choosing a strategy. According to the goal of TSP, it is not difficult to conclude that the lower the cost of the path, the higher the adaptability, while the fitness value must be positive. Therefore, the degree of adaptability is the reciprocal of the path cost.

Select action: Roulette + Elite Selection

INPUT: Initial population popu[m]output: Select the population newpopu[m]beginsumfit=0.0; For (K=0;k<popu.size (); k++) Sumfit+=popu[k].fit; End forfor (i=0,k=0;i<m-1;i++) p=random ()%1000/1000.0;//randomly generates a probability sump=0; For (J=0;j<popu.size (); j + +) sump=sump+ (popu[j].fit)/sumfit;if (sump>p) break; End IfEnd Fornewpopu[k++]=popu[j]; End Forsort (popu)//fit from large to small sort newpopu[k]=popu[0];//elites put in the last end

Cross Strategy

In the course of natural evolution of organisms, two homologous chromosomes are reconstituted by mating to form new chromosomes, resulting in new individuals or species. Mating recombination is a major link in the process of biological heredity and evolution. Imitating this link, crossover operators are also used in genetic algorithms to generate new individuals. The so-called crossover operation in the genetic algorithm refers to the exchange of some genes between two pairs of chromosomes in some way, thus forming two new individuals. For the TSP problem, crossover is not just a partial exchange of two individual genes, but it must also ensure that the new individuals that are produced after the exchange of genes must contain all cities without duplication. This is a difficult and important point in the design of TSP crossover, and it is not a cross-operation for each individual, but a PC based on a certain crossover probability.

The common crossover algorithms in genetic algorithms are single-point crossover, multi-point crossover, uniform crossover and arithmetic crossover. A single-point crossover, also known as a simple crossover, refers to the random setting of an intersection in an individual code string, and then a partial chromosome that exchanges two pairs of individuals at that point. Multi-point crossing refers to randomly setting multiple intersections in individual coded strings and then gene Exchange. Multi-point intersections are also called generalized intersections. The common point is a double-dot crossover. The genes on each of the two paired individuals are exchanged with the same crossover probabilities, resulting in two new individuals. A uniform cross can actually belong to a range of multipoint intersections. A linear combination of two individuals produces two new individuals, often used in genetic algorithms for calculating function values.

Cross (Popu[m])//Crossover policy input: Selected population popu[m]output: After the cross of the population Newpopu[m]begin for       (I=0;i<popu.size () -1;i++)// The last individual is unconditionally reserved for the optimal individual in the population       p=random ()%1000/1000.0;//randomly generates a probability       If (P<PC)//with probability PC crossover              j=random ()% (Popu.size () -1)              Xcross (Popu[i],popu[j])              Fit (Popu[i]);              Fit (Popu[j]);              if (popu[i].fit>popu[m-1].fit) swap (popu[i],popu[m-1]), if (popu[j].fit>popu[m-1].fit) swap (popu[j],popu[m-1] );       Endifend forend

Overall, the probability of the algorithm p crosses the first M-1 elements. If the crossover is higher than the current optimal value popu[m-1], then the current optimal is exchanged. This ensures that the optimal individual in the population (the last one) can always inherit 100% from the next generation. After crossing, recalculate its fitness and prepare for the mutation operation. where the Xcross () function is randomly generating two intersections, and then exchanging elements inside the intersection point. Other elements follow the Fill method, and the remaining elements are added to the individual from a second intersection. After mutation, if the individual is higher than the current optimal value, then the current optimal and the mutation after the individual exchange.

Take two parents for example: (1 2 3 4 5 6 7 8) and (2 4 6 8 7 5 3 1), randomly select two crossed points, if the first point is position 3 and the second intersection is position 5, then the position between the two points will be crossed. In this instance, 3 4 5 is selected in the first parent, and 6 8 7 is selected in the second parent. The elements in the interchange crossover range become (1 2 6 8 7 6 7 8) and (2 4 3 4 5 5 3 1), and then start with the second intersection, populate the original corresponding parent in order, and then start with the 6th element, if the selected element already exists in the descendant, skip the element (1 6 7 skip), select The next element, this process is repeated until all cities are selected once. The final transformed descendants are (4 5 6 8 7 1 2 3) and (8 7 3 4 5 1 2 6).


Mutation Strategy

The crossover operation is the main method to produce the new individual, it determines the global searching ability of the genetic algorithm, and the mutation operation is the auxiliary method of the new individual, but it is also an essential operation step, because it determines the local search ability of the genetic algorithm. The crossover operator and mutation operator cooperate with each other to complete the global search and local search of search space, so that the genetic algorithm can complete the optimization process with good search performance.

The common mutation operations include substitution mutation, switching mutation, insertion variation and simple inverted mutation. Substitution mutation is the first selection of a gene from the parent, then randomly randomly selects a position in the remaining gene and inserts the selected gene segment. The Exchange mutation is the selection of two genes, and then the location of two genes exchanged. The insertion mutation belongs to the special case of the substitution mutation, selecting only one gene to insert instead of the gene segment. Simple inverted mutation is to randomly select a gene and then reverse it. This article chooses the Exchange mutation. For each gene according to a certain probability of mutation selection, if selected, then randomly choose from the remaining genes to exchange with.


Code:

#include <iostream> #include <vector> #include <algorithm> #include <cmath> #include <ctime > #include <fstream> #include <iterator> #include <cstring> #define MAX 0x37777777#define maxcity    300#define RANGE 500using namespace std;struct point{int x;    int y; char name;};    struct answer{double cost; Vector<int> path;};/  /genetic parameter int citynum=52;     City number double pc=0.8;     Crossover probability double pm=0.2;      mutation probability int m=9;   Population size int g=10000; Iteration count Double dist[maxcity][maxcity]={0}; Point Citys[maxcity];//city ' s coordinate//read the graph & compute the distance dist[i][j]void initgraph (int citynum)    {FStream fileRead;    Char filename[20];    sprintf (FileName, "City_coor_%d.txt", citynum);    Fileread.open (filename,ios::in);        for (int i=0;i<citynum;i++) {int temp;        fileread>>temp>>citys[i].x>>citys[i].y; cout<<temp<< "--" <<citys[i].x<< "--" <<citys[i].y<< Endl;    } fileread.close ();    memset (dist,0,sizeof (Dist)); for (int i=0;i<citynum;i++) {for (int j=0;j<citynum;j++) {if (j!=i&&dist[i][j]==0 ) {double d2= (citys[i].x-citys[j].x) * (citys[i].x-citys[j].x) + (CITYS[I].Y-CITYS[J].Y) * (Citys[i].                Y-CITYS[J].Y);            DIST[I][J]=DIST[J][I]=SQRT (D2);    }}}}void Initpopu (vector<answer> &popu) {Answer Answer;    Generate population for (int i=0;i<citynum;i++) {answer.path.push_back (i);        } for (int i=0;i<m;i++) {int first=0,second=0;        First=rand ()%citynum;        Second=rand ()%citynum;            if (First>second)//promise First<=second {first=first^second;            Second=first^second;        First=first^second;        }//cout<<first<< "--" <<second<<endl; if (First!=second) {random_shuffle (Answer.path.begin () +fiRst,answer.path.begin () +second);        } popu.push_back (answer); Copy (Popu[i].path.begin (), Popu[i].path.end (),ostream_iterator<int> (cout, "")); cout<<endl;//    Output Answer}}void cost (Answer &answer) {double sum=0;    for (int i=0;i+1< (answer.path). Size (); i++) {sum+=dist[(Answer.path) [i]][(Answer.path) [i+1]];    } sum+=dist[(Answer.path) [(Answer.path). Size () -1]][(Answer.path) [0]]; Answer.cost=sum;} BOOL Cmp (const Answer & a1,const Answer & A2) {return a1.cost<a2.cost;}    void Choose (vector<answer> &popu) {vector<answer> newpopu;    Double sumfits=0;    Double fits=0;    for (int j=0;j<popu.size (); j + +) {sumfits+= (1.0/popu[j].cost);        } for (int i=0;i<m-1;i++) {double random= (rand ()%998)/997.0;        fits=0;        int num=0;            for (int j=0;j<popu.size (); j + +) {fits+= (1.0/popu[j].cost/sumfits); if (fits>=random) {num=j;//Select num break;    }} newpopu.push_back (Popu[num]);    } sort (Popu.begin (), Popu.end (), CMP); Newpopu.push_back (popu[0]);//Elite selection, inserted in the last Swap (POPU,NEWPOPU);}    void Cro1 (Answer &a1,answer &a2)//partially matched cross {Answer a11=a1,a22=a2;    int first=0,second=0;    First=rand ()%citynum;    Second=rand ()%citynum;        if (First>second)//promise First<=second {first=first^second;        Second=first^second;    First=first^second;    } int parent1[maxcity],parent2[maxcity];    memset (parent1,0,sizeof (parent1));    memset (parent2,0,sizeof (Parent2));        for (int j=first;j<second;j++) {parent1[a2.path[j]]=1;        Parent2[a1.path[j]]=1;        A1.PATH[J]=A1.PATH[J]^A2.PATH[J];        A2.PATH[J]=A1.PATH[J]^A2.PATH[J];        A1.PATH[J]=A1.PATH[J]^A2.PATH[J];        int TEMP=A1.PATH[J];        A1.PATH[J]=A2.PATH[J];        A2.path[j]=temp;        A1.path[j]= (A1.path[j]) + (a2.path[j]); A2.path[j]= (a1.path[J])-(a2.path[j]);        A1.path[j]= (A1.path[j])-(a2.path[j]);    cout<< a1.path[j]<< "" << a2.path[j]<<endl;    } int K1=second,k2=second;        for (int j=second;j<citynum;j++) {//a1 int cur=a11.path[j];            if (parent1[cur]==0) {a1.path[k1++]=cur;            if (k1>=citynum) k1=0;        Parent1[cur]=1;        }//a2 Cur=a22.path[j];            if (parent2[cur]==0) {a2.path[k2++]=cur;            if (k2>=citynum) k2=0;        Parent2[cur]=1;        }} for (int j=0;j<second;j++) {//a1 int cur=a11.path[j];            if (parent1[cur]==0) {a1.path[k1++]=cur;            if (k1>=citynum) k1=0;        Parent1[cur]=1;        }//a2 Cur=a22.path[j];            if (parent2[cur]==0) {a2.path[k2++]=cur;            if (k2>=citynum) k2=0;        Parent2[cur]=1; }}//copy (A1.path.begin (), A1.path.enD (),ostream_iterator<int> (cout, "")), cout<<endl;//output Answer//copy (A2.path.begin (), A2.path.end (), Ostream_iterator<int> (cout, "")) cout<<endl;//output answer}void Cro2 (Answer &a1,answer &a2)//    Partially matched cross {Answer a11=a1,a22=a2;    int first=0,second=0;    First=rand ()%citynum;    Second=rand ()%citynum;        if (First>second)//promise First<=second {first=first^second;        Second=first^second;    First=first^second;    } int parent1[maxcity],parent2[maxcity];    memset (parent1,-1,sizeof (parent1));    memset (parent2,-1,sizeof (Parent2));        for (int j=first;j<second;j++) {parent1[a2.path[j]]=a1.path[j];        PARENT2[A1.PATH[J]]=A2.PATH[J];        A1.PATH[J]=A1.PATH[J]^A2.PATH[J];        A2.PATH[J]=A1.PATH[J]^A2.PATH[J];        A1.PATH[J]=A1.PATH[J]^A2.PATH[J];        int TEMP=A1.PATH[J];        A1.PATH[J]=A2.PATH[J];    A2.path[j]=temp;    } int K1=second,k2=second;     for (int j=second;j<citynum;j++) {   A1 int Cur=a11.path[j];        while (Parent1[cur]!=-1) {cur=parent1[cur];        } a1.path[k1++]=cur;        if (k1>=citynum) k1=0;        A2 Cur=a22.path[j];        while (Parent2[cur]!=-1) {cur=parent2[cur];        } a2.path[k2++]=cur;    if (k2>=citynum) k2=0;        } for (int j=0;j<first;j++) {//a1 int cur=a11.path[j];        while (Parent1[cur]!=-1) {cur=parent1[cur];        } a1.path[k1++]=cur;        if (k1>=citynum) k1=0;        A2 Cur=a22.path[j];        while (Parent2[cur]!=-1) {cur=parent2[cur];        } a2.path[k2++]=cur;    if (k2>=citynum) k2=0; }//copy (A1.path.begin (), A1.path.end (),ostream_iterator<int> (cout, "")); cout<<endl;//Output Answer//copy ( A2.path.begin (), A2.path.end (),ostream_iterator<int> (cout, "")); cout<<endl;//Output Answer}void Cross ( Vector<answer> &newpopu) {foR (int i=0;i<newpopu.size () -1;i++) {Double random= (rand ()%998)/997.0;            if (random<pc) {int first=i;            int Second=rand ()% (Newpopu.size ()-1);            Cross Cro2 (Newpopu[first],newpopu[second]);            Cost (Newpopu[first]);            Cost (Newpopu[second]);            if (newpopu[first].cost<newpopu[m-1].cost) swap (newpopu[first],newpopu[m-1]);        if (newpopu[second].cost<newpopu[m-1].cost) swap (newpopu[second],newpopu[m-1]); }}}void Variation (Vector<answer> &newpopu) {for (int i=0;i<newpopu.size () -1;i++) {double ran        Dom= (rand ()%998)/997.0;            if (random<pm) {int first=rand ()%citynum;            int Second=rand ()%citynum;            Variant int Temp=newpopu[i].path[first];            Newpopu[i].path[first]=newpopu[i].path[second];            Newpopu[i].path[second]=temp;            Cost (Newpopu[i]); if (newpopu[i].cost<newpopu[m-1].cost) swap (newpopu[i],newpopu[m-1]);    }}}void Save (Answer Answer) {fstream fileWrite;    Filewrite.open ("OUT.txt", Ios::out|ios::app); filewrite<< "Number of cities:" <<CITYNUM<< "; Population size:" <<M<< "; crossover probability:" <<PC<< "; mutation probability:" <    <PM<< "; Algebra:" <<G<<endl;    filewrite<< "Minimum cost:" <<answer.cost<<endl; Filewrite.close ();}    Double GA () {vector<answer> popu;         Initgraph (Citynum)//read the citys & Compute Dist Initpopu (POPU);//Initialize the population for (int i=0;i<popu.size (); i++) {    Cost (Popu[i]);        } int k=0;//k algebra for (; k<g;k++) {//select (Elite selection 1+ Roulette selection) Choose (POPU);        Cross crosses (Popu);        Variant Variation (POPU);    cout<<k<< ":" << (Popu[8]). cost<<endl;//the best price for the K-th iteration} sort (Popu.begin (), Popu.end (), CMP);    Save (Popu[0]); Copy ((Popu[0]). Path.begin (), (Popu[0]). Path.end (),ostream_iterator<int> (cout, "")); cout<<endl;//  Output answer  cout<< (popu[0]) .cost<<endl; Return (Popu[0]). Cost;} /*************************************************************//above is the Genetic algorithm section//Below is the experimental section///Generate 7 problem size files//Save the experimental results *******    /void generatecity (int citynum) {fstream fileWrite;    Char filename[20];    sprintf (FileName, "City_coor_%d.txt", citynum);    Filewrite.open (Filename,ios::out|ios::app); filewrite<< "Number of cities:" <<CITYNUM<< "; Population size:" <<M<< "; crossover probability:" <<PC<< "; mutation probability:"    <<PM<< "; Algebra:" <<G<<endl;    filewrite<< "Minimum cost:" <<answer.cost<<endl;        for (int i=0;i<citynum;i++) {//filewrite<<citys[answer.path[i]].name<< ",";        Citys[i].x=rand ()%range;        Citys[i].y=rand ()%range;    filewrite<<i<< "\ t" <<citys[i].x<< "\ T" <<citys[i].y<<endl; } filewrite.close ();}        void populationtest (int citynums[]) {for (int i=6;i<7;i++) {Initgraph (Citynums[i]);        Citynum=citynums[i];        FStream FileWrite;        Char filename[30];        sprintf (FileName, "Out_city_%d_popu.txt", citynum);        Filewrite.open (Filename,ios::out|ios::app);        filewrite<< "ratio" << ' \ T ' << "best" << ' \ t ' << ' mean ' << ' \ t ' << ' worst ' <<endl; for (int j=1;j<=9;j++) {m=citynum*j/10;//1/10 2/10 3/10 ...            9/10 pc=0.8;            pm=0.2;            G=500*citynum;            Double sum=0,avgcost=0,mincost=max,maxcost=0;                for (int k=0;k<10;k++) {double Temp=ga ();                Sum+=temp;                if (temp<mincost) mincost=temp;            if (temp>maxcost) maxcost=temp; } filewrite<<j<< "0%" << ' \ t ' <<minCost<< ' \ t ' <<sum/10<< ' \ t ' <<maxcos        t<<endl;    } filewrite.close (); }}void crossvartest (int citynums[],double crossp[],double varp[]){for (int i=0;i<7;i++) {initgraph (citynums[i]);        Citynum=citynums[i];            for (int j=0;j<11;j++) {if (citynum<100) M=CITYNUM*9/10;            else if (citynum>=100&&citynum<200) M=CITYNUM*4/10;            else m=40;            PC=CROSSP[J];            G=200*citynum;            FStream FileWrite;            Char filename[50];            sprintf (FileName, "Out_%d_cross_%.2f.txt", citynum,pc);            Filewrite.open (Filename,ios::out|ios::app);            filewrite<< variations << ' t ' << best << ' \ t ' << ' mean ' << ' \ t ' << ' worst ' <<endl;                for (int u=0;u<12;u++) {pm=varp[u];                Double sum=0,avgcost=0,mincost=max,maxcost=0;                    for (int k=0;k<10;k++) {double Temp=ga ();                    Sum+=temp;                    if (temp<mincost) mincost=temp;           if (temp>maxcost) maxcost=temp;     } filewrite<<pm<< ' \ t ' <<minCost<< ' \ t ' <<sum/10<< ' \ t ' <<maxcost&            lt;<endl;        } filewrite.close ();    }}}int Main () {Srand (Unsigned (Time (NULL)));    int citynums[7]={10,20,30,50,70,100,200};    Double crossp[11]={0.01,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,0.99};    Double varp[12]={0.001,0.01,0.05,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9};    for (int i=0;i<7;i++)//{//generatecity (Citynums[i]);    }//populationtest (Citynums);    Crossvartest (CITYNUMS,CROSSP,VARP);    Srand (Unsigned (Time (NULL)));    g=100000;    Initgraph (200);    GA (); return 0;}




Solving tsp problem by genetic algorithm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.