1. Purpose of the experiment:
Familiar with and master the principle, process and coding strategy of genetic algorithm, and use genetic algorithm to solve combinatorial optimization problems, understand the process of solving TSP problems and test the influence of main parameters on the results.
2. Experimental principle:
The traveling salesman problem, TSP problem (Traveling Salesman Problem) is one of the famous problems in the field of mathematics. Assuming that a traveling businessman wants to visit n cities, he must choose the path he wants to take. The limit of the route is that each city can only be visited once, and finally he must return to the original city from which he started. The goal of path selection is that the required path distance is the minimum value among all paths. The TSP problem is a combinatorial optimization problem. The problem can be shown to have NPC computational complexity. Therefore, any method that can simplify the solution of this problem will be highly evaluated and paid attention to.
The basic principle of the genetic algorithm is to solve the problem by acting on the genes on the chromosome to find a good chromosome. It needs to evaluate each chromosome generated by the algorithm, and select the chromosome based on the fitness value, so that the chromosome with good adaptability has More breeding opportunities. In the genetic algorithm, a number of digital codes of the problem to be solved are randomly generated, that is, chromosomes, to form the initial population; each individual is given a numerical evaluation through the fitness function, and individuals with low fitness are eliminated. Individuals with high fitness are selected to participate in the genetic operation, and the collection of individuals after the inheritance operation forms a new population of the next generation, and the next round of evolution is carried out on this new population. This experiment requires the use of genetic algorithm to solve the shortest path of the TSP problem.
3. Experimental content:
1. Refer to the core code of the genetic algorithm given by the experimental system. It is required to use the genetic algorithm to solve different scales (such as 10 cities, 30 cities, and 100 cities) under the same population size, maximum number of iteration steps, and number of independent operations. Fill in the results in Table 1 for the TSP problem.
Table 1 The results of genetic algorithm for solving TSP problems of different scales
city size |
population size |
Maximum number of iterations |
number of independent runs |
best fitness |
worst fitness |
average fitness |
average running time |
10 |
100 |
100 |
10 |
25.1652 |
25.8521 |
25.3501 |
47 p |
30 |
100 |
100 |
10 |
10605.7 |
11868 |
11281.2 |
122.8s |
100 |
100 |
100 |
10 |
44334.9 |
47149.1 |
46117.6 |
484.2s |
- Set the population size to 100, the crossover probability to 0.8, and the mutation probability to 0.8, and then add a mutation strategy (such as two adjacent points exchange mutation, reverse mutation or insertion mutation, etc.) and an individual selection probability allocation strategy (such as by Linear sorting or assigning individual selection probabilities according to nonlinear sorting) is used to solve the TSP problem of 30 cities (the coordinates of the 30 cities are as follows), and the results are filled in Table 2.
30 city coordinates:
x[0]=41, x[1]=37,x[2]=54,x[3]=25,x[4]=7,x[5]=2,x[6]=68,x[7]=71,x[8]=54,x[9]=83;
y[0]=94,y[1]=84,y[2]=67,y[3]=62,y[4]=64,y[5]=99,y[6]=58,y [7]=44,y[8]=62,y[9]=69;
x[10]=64,x[11]=18,x[12]=22,x[13]=83,x[14]=91,x[15]=25,x[16]=24,x[17]=58,x[18]=71,x[19]=74;
y[10]=60,y[11]=54,y[12]=60,y[13]=46,y[14]=38,y[15]=38,y[16]=42,y [17]=69,y[18]=71,y[19]=78;
x[20]=87,x[21]=18,x[22]=13,x[23]=82,x[24]=62,x[25]=58,x[26]=45,x[27]=41,x[28]=44, x[29]=4;
y[20]=76,y[21]=40,y[22]=40,y[23]=7,y[24]=32,y[25]=35,y[26]=21,y [27]=26,and[28]=35; y[29]=50;
Table 2 The solution results of different mutation strategies and individual selection probability assignment strategies
mutation strategy |
individual choice probability assignment |
Maximum number of iterations |
number of independent runs |
best fitness |
worst fitness |
average fitness |
average running time |
two point swap |
Proportional distribution according to fitness |
100 |
10 |
889.434 |
982.154 |
938.503 |
59s |
two point swap |
Sort linearly |
100 |
10 |
488.833 |
567.304 |
513.735 |
51s |
Swap two adjacent points |
Sort linearly |
100 |
10 |
1022.77 |
1104.54 |
1064.78 |
49.1s |
Swap two adjacent points |
Proportional distribution according to fitness |
100 |
10 |
878.549 |
969.802 |
939.414 |
58s |
3. Given the data of 34 provincial capitals in China, it is required to design an improved genetic algorithm based on this data to solve the TSP problem. It is required to give 1) the improved algorithm strategy and core code, 2) the main parameter settings of the improved algorithm (population size, crossover probability, mutation probability, maximum number of iteration steps, etc.), 3) the shortest distance between the 34 provincial capitals finally obtained by the improved algorithm Path value, optimal individual and algorithm running time, 4) Given the same parameter settings (population size, crossover probability, mutation probability, maximum number of iteration steps, etc.), using the basic genetic algorithm (without using the improved strategy) to obtain The shortest path value, optimal individual and algorithm running time of the 34 provincial capitals.
Figure 1 Location of 34 provincial capitals in China (1295.72)
Table 3 34 provincial capital cities and pixel coordinate table
City |
Tibet |
Yunnan |
sichuan |
Qinghai |
Ningxia |
Gansu |
Inner Mongolia |
Heilongjiang |
Jilin |
liaoning |
Beijing |
Tianjin |
city number |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
X coordinate |
100 |
187 |
201 |
187 |
221 |
202 |
258 |
352 |
346 |
336 |
290 |
297 |
Y coordinate |
211 |
265 |
214 |
158 |
142 |
165 |
121 |
66 |
85 |
106 |
127 |
135 |
City |
Hebei |
Shandong |
Henan |
Shanxi |
Shaanxi |
Anhui |
Jiangsu |
Shanghai |
zhejiang |
Jiangxi |
Hubei |
Hunan |
city number |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
X coordinate |
278 |
296 |
274 |
265 |
239 |
302 |
316 |
334 |
325 |
293 |
280 |
271 |
Y coordinate |
147 |
158 |
177 |
148 |
182 |
203 |
199 |
206 |
215 |
233 |
216 |
238 |
City |
Guizhou |
Guangxi |
Guangdong |
Fujian |
Hainan |
Macao |
Hongkong |
Taiwan |
chongqing |
Xinjiang |
||
city number |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
||
X coordinate |
221 |
233 |
275 |
322 |
250 |
277 |
286 |
342 |
220 |
104 |
||
Y coordinate |
253 |
287 |
285 |
254 |
315 |
293 |
290 |
263 |
226 |
77 |
x[0]=100, x[1]=187,x[2]=201,x[3]=187,x[4]=221,x[5]=202,x[6]=258,x[7]=352,x[8]=346,x[9]=336;
y[0]=211,y[1]=265,y[2]=214,y[3]=158,y[4]=142,y[5]=165,y[6]=121,y [7]=66,y[8]=85,y[9]=106;
x[10]=290,x[11]=297,x[12]=278,x[13]=296,x[14]=274,x[15]=265,x[16]=239,x[17]=302,x[18]=316,x[19]=334;
y[10]=127,y[11]=135,y[12]=147,y[13]=158,y[14]=177,y[15]=148,y[16]=182,y [17]=203,y[18]=199,y[19]=206;
x[20]=325,x[21]=293,x[22]=280,x[23]=271,x[24]=221,x[25]=233,x[26]=275,x[27]=322,x[28]=250, x[29]=277;
y[20]=215,y[21]=233,y[22]=216,y[23]=238,y[24]=253,y[25]=287,y[26]=285,y [27]=254,and[28]=315; y[29]=293;
x[30]=286, x[31]=342,x[32]=220,x[33]=104;
y[30]=290,y[31]=263,y[32]=226,y[33]=77;
3.1 Results:
3.1.1 Here are two experimental results, the difference is only the initial starting point is different
① Draw the path as shown in Figure 2 (based on python, starting point 15):
Fig. 2 Plot showing the optimal solution
Shortest path length 1532.3994414550848
Path representation: [23, 32, 24, 1, 2, 0, 33, 3, 5, 4, 12, 14, 16, 22, 21, 27, 31, 30, 26, 29, 28, 25, 20, 19, 18, 17, 13, 11, 9, 8, 7, 10, 6]
The path length decreases with the number of iterations:
Figure 3 The relationship between the number of iterations and the optimal solution
② Draw the path as shown in the figure (based on python, starting point 32):
Figure 4 is a plot showing the optimal solution
Shortest path length: 1551.0699954694958
Path representation: [1, 28, 25, 24, 18, 20, 19, 31, 27, 29, 30, 26, 23, 21, 22, 16, 14, 17, 13, 9, 8, 7, 11, 10, 12, 15, 6, 4, 5, 0, 33, 3, 2]
The path length decreases with the number of iterations:
Figure 5 The relationship between the optimal solution and the number of iterations
3.1.2
If not improved, use the original program, and the parameters are set as follows (based on C++):
Chromosome length: 34
Maximum iteration steps: 500
Population size: 100
Crossover Probability: 0.5
Mutation probability 0.15
Selection operation: distribute the selection probability of individuals according to the fitness ratio, and select individuals by roulette
Crossover Operation: PMX Crossover
Mutation operation: swap two adjacent points
The result is shown in Figure 6:
Figure 6 Results
The optimal path length is: 6246.62
Path: 32-20-18-21-28-29-26-24-13-30-12-10-31-33-2-3-1-7-9-4-15-11-0-5- 8-6-17-16-23-25-19-22-27-14
The running time is: 214.6s
It can be seen that the improved algorithm is quite effective.
3.2 Improved algorithm strategy and core code :
①Parameter setting:
#population number
count=300
#Improve times
improve_count=10000
#Evolution times
itter_time=3000
#Set the definition probability of the strong, that is, the top 30% of the population are the strong
retain_rate=0.3
#Set the survival probability of the weak
random_select_rate=0.5
#mutation rate
mutation_rate=0.1
②Path coding:
Number the cities 0, 1, 2, 3...33, chromosome {x1, x2, x3...x33}, which means starting from x1, going through x2, x3....x33 and then returning to x1 , the starting point can be set arbitrarily, in this program it is set to 15.
③ Initialize the population:
In order to speed up the running speed of the program, some better individuals should be selected in the selection of the initial population. First use the classical approximation algorithm—improved circle algorithm to obtain a better initial population. The idea of the algorithm is to randomly generate a chromosome, such as {1, 2, ... 33}, exchange the sequential positions of the two cities arbitrarily, if the total distance decreases, update and change the chromosome, and repeat until no further modification can be made.
code:
#Initialize population
population = []
for i in range(count):
# Randomly generate individuals
x = index.copy()
random.shuffle(x)
improve(x)
population.append(x)
# improvement
def improve(x):
i=0
distance=get_total_distance(x)
while i<improve_count:
# randint [a,b]
u=random.randint(0,len(x)-1)
v = random.randint(0, len(x)-1)
if u!=v:
new_x=x.copy()
t=new_x[u]
new_x[u]=new_x[v]
new_x[v]=t
new_distance=get_total_distance(new_x)
if new_distance<distance:
distance=new_distance
x=new_x.copy()
else:
continue
i+=1
④Select strategy:
Although the roulette wheel method is the most used selection strategy, this strategy may produce large sampling errors. Therefore, this uses natural selection to calculate the distance between each city and store it in the matrix. The total distance Sort from small to large, select the chromosomes with strong adaptability, and then select the chromosomes with less adaptability but surviving chromosomes (random selection).
Core code:
# natural selection
def selection(population):
# Sort the total distance from small to large
graded = [[get_total_distance(x), x] for x in population]
graded = [x[1] for x in sorted(graded)]
# Select the most adaptive chromosomes
retain_length = int(len(graded) * retain_rate)
parents = graded[:retain_length]
# Select less adaptive but surviving chromosomes
for chromosome in graded[retain_length:]:
if random.random() < random_select_rate:
parents.append(chromosome)
return parents
⑤ Variation strategy:
According to the given mutation rate, randomly select three integers for the selected mutated individuals, satisfying 1<u<v<w<33, and insert the gene segment between v and u (including u and v) into w later. Replace the original two adjacent point swap mutation, and the mutation strategy of two point swap.
Core code:
#Mutations
def mutation(children):
for i in range(len(children)):
if random.random() < mutation_rate:
child=children[i]
u=random.randint(1,len(child)-4)
v = random.randint(u+1, len(child)-3)
w= random.randint(v+1, len(child)-2)
child=children[i]
child=child[0:u]+child[v:w]+child[u:v]+child[w:]
4. Submit the experiment report and source program.
3. Experimental results :
Experimental content 1 result:
Table 1 The results of genetic algorithm for solving TSP problems of different scales
city size |
population size |
Maximum number of iterations |
number of independent runs |
best fitness |
worst fitness |
average fitness |
average running time |
10 |
100 |
100 |
10 |
25.1652 |
25.8521 |
25.3501 |
47 p |
30 |
100 |
100 |
10 |
10605.7 |
11868 |
11281.2 |
122.8s |
100 |
100 |
100 |
10 |
44334.9 |
47149.1 |
46117.6 |
484.2s |
Experimental content 2 results:
Table 2 The solution results of different mutation strategies and individual selection probability assignment strategies
mutation strategy |
individual choice probability assignment |
Maximum number of iterations |
number of independent runs |
best fitness |
worst fitness |
average fitness |
average running time |
two point swap |
Proportional distribution according to fitness |
100 |
10 |
889.434 |
982.154 |
938.503 |
59s |
two point swap |
Sort linearly |
100 |
10 |
488.833 |
567.304 |
513.735 |
51s |
Swap two adjacent points |
Sort linearly |
100 |
10 |
1022.77 |
1104.54 |
1064.78 |
49.1s |
Swap two adjacent points |
Proportional distribution according to fitness |
100 |
10 |
878.549 |
969.802 |
939.414 |
58s |
The result of experiment content 3, located in experiment content 3:
The path is shown in Figure 2:
Shortest path length 1532.3994414550848
Path representation: [23, 32, 24, 1, 2, 0, 33, 3, 5, 4, 12, 14, 16, 22, 21, 27, 31, 30, 26, 29, 28, 25, 20, 19, 18, 17, 13, 11, 9, 8, 7, 10, 6]
4. Experimental thinking and experience :
1. Analyze the algorithm performance of genetic algorithm for solving TSP problems of different scales.
The larger the city size, the larger the number of iterations, the longer the search for the optimal solution, and the longer the waiting time for the result.
2. Add 1 mutation strategy and 1 individual selection probability distribution strategy, and compare the influence of different mutation strategies and individual selection distribution strategies on the algorithm results when solving TSP problems in 30 cities.
Added adjacent two-point mutation and linear sorting to select individuals:
Mutation strategy:
void change1(vector<int>& K, int N){//mutation strategy: exchange mutation between two adjacent points
int i = next_int() % N;
swap(K[i], K[(i + 1) % N]);
}
Individual selection strategy:
if(make_p==1)//linear sort
{
for(int i=0;i<popsize;i++)
ps[i]=(200-2*i)/popsize*(popsize+1);
}
From the experimental results, the linear sorting is better, and the random two-point exchange strategy is obviously better than the adjacent two-point exchange strategy.
3. Comparatively analyze the influence of the improved strategy of the genetic algorithm on the results of solving the TSP problems of 34 cities.
The main reason is that a relatively large improvement has been made in the selection of the fitness value. The better individuals are selected first, and some poor individuals are randomly selected. By improving the code of some parameters, selection and mutation, you can make what you want to get The optimal solution of is better. If the improvement is not used, the optimal solution that can be obtained in the final operation is about 7.8 thousand, as shown in Figure 7, and the accuracy is far from enough.
Figure 7 Unimproved running results
4. Summarize the experience of the experiment:
There are many other improvement strategies, such as:
①Using the greedy algorithm to initialize the population, the basic idea of each individual generation is: first randomly select the city ccurrent from n cities as the first gene, and then find the city cnext (cnext) from the remaining n-1 cities cnext is the city closest to ccurrent) as the second gene, and then find the city cnext+1 from the remaining n-2 cities (cnext+1 is the city closest to cnext) as the third gene, and so on until Traverse n cities so far. The proportion of some populations generated by the greedy algorithm is not large. While improving the overall quality of the initial population, it will not affect the diversity of the initial population, which helps to speed up the optimization speed. Because I am not very familiar with the code, I failed to change it to a greedy algorithm to initialize the population.
② It is also possible to appropriately enlarge the fitness and consider the fractional part, but from the results of the experimental run, it is not very meaningful. The optimal solution is relatively average, and the distance is still quite large.
③Improved crossover operator: the two-point crossover operator commonly used in basic genetic algorithms. This crossover method only crosses the genes between the two points of the parent individual. The genes outside the two points are either unchanged or blind due to node duplication. The good genes of the parent cannot be effectively inherited. Two-point three-segment random crossover can be used.
Unimproved source code:
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<time.h>
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
#define PB push_back
#define MP make_pair
int next_int()
{
return rand()*(RAND_MAX+1)+rand();
}
double next_double()
{
return (double(rand()*(RAND_MAX+1)+rand()))/((RAND_MAX+1)*RAND_MAX+RAND_MAX);
}
void pmx(VI& a,VI& b,int pointcnt)//PMX交叉
{
int sa=next_int()%pointcnt,sb=next_int()%pointcnt;//随机选择两交叉位
int temp;
if (sa>sb)
{
temp=sa;
sa=sb;
sb=temp;
}//保证交叉位sa<=sb
VI aa(pointcnt),bb(pointcnt);
int i;
for(i=0;i<pointcnt;i++)
{
aa[i]=a[i],bb[i]=b[i];
}
VI m1(pointcnt,-1);
VI m2(pointcnt,-1);
VI v1tov2(pointcnt,-1);
for(i=sa;i<=sb;i++)
{
m1[aa[i]]=-2; //m1存放aa非交叉段可代换的基因
m2[bb[i]]=-2; //m2存放aa非交叉段可代换的基因
}
for(i=0;i<pointcnt;i++) {
if(m2[i]==m1[i])//去掉m1和m2中重复代换的基因
{
m2[i]=-1;
m1[i]=-1;
}
}
int aaa=0;
for(i=sa;i<=sb;i++)
{
if ((m1[aa[i]]==-2)&&(m2[bb[i]]==-2))
{
v1tov2[aa[i]]=bb[i];//v1tov2存放首先可以确定的互换基因
m1[aa[i]]=-1;
m2[bb[i]]=-1;
aaa++;
}
}
if(aaa!=(sb-sa+1))
{
for(i=0;i<pointcnt;i++)
if (m1[i]==-2)
{
int aflag=0;
for(int j=0;j<pointcnt;j++)
if( (m2[j]==-2) && (aflag==0))//寻找并确定可以互换的基因
{
v1tov2[i]=j;
aflag=1;
aaa++;
m2[j]=-1;
m1[i]=-1;
}
}
}
for(i=sa;i<=sb;i++) {
swap(aa[i],bb[i]); //交换sa到sb之间的基因串
}
for(i=0;i<pointcnt;i++)//查找染色体aa中sa之前和sb之后的基因是否有重复
{
if ((i<sa)||(i>sb))
for (int j=sa;j<=sb;j++)
{
if(aa[i]==aa[j]) //有重复基因
{
for(int k=0;k<pointcnt;k++)
if(aa[i]==v1tov2[k])
aa[i]=k; //进行互换
}
}
}
for(i=0;i<pointcnt;i++)//查找染色体bb中sa之前和sb之后的基因是否有重复
{
if ((i<sa)||(i>sb))
for (int j=sa;j<=sb;j++)
{
if(bb[i]==bb[j]) //有重复基因
bb[i]=v1tov2[bb[i]]; //进行互换
}
}
a=aa;
b=bb;
}
vector<double> x,y;
double fitness(const VI& v,int pointcnt)//计算适应度
{
double r=0;
for(int i=0;i<pointcnt;i++)
{
double dx=x[v[i]]-x[v[(i+1)%pointcnt]];
double dy=y[v[i]]-y[v[(i+1)%pointcnt]];
r+=sqrt(dx*dx+dy*dy);//个体的适应度为相邻两城市之间的距离平方的平方根和
}
return 1.0/r;
}
void change0(vector<int>& K,int N)//变异策略:两点互换
{
int i=next_int()%N;
int d=next_int()%(N-1);
int j=(i+1+d)%N;
swap(K[i],K[j]);
}
void change1(vector<int>& K, int N){//变异策略:相邻两点互换变异
int i = next_int() % N;
swap(K[i], K[(i + 1) % N]);
}
void mutate(VI& route,int mutate_type,int pointcnt)
{
if(mutate_type==0)//两点互换
change0(route,pointcnt);
if(mutate_type==1)//相邻两点互换变异
change1(route,pointcnt);
}
bool pair_dec(const pair<double,VI*>& a,const pair<double,VI*>& b)
{
return a>b;
}
class other_population
{
public:
int popsize,pointcnt;//种群规模,染色体长度
double pc,pm;//交叉概率,变异概率
vector<pair<double,VI*> >pop;//种群
pair<double,VI*> bestofpop;//最好个体
int cross_type;//交叉类型
int mutate_type;//变异类型
int make_p;//个体概率分配策略类型
int select_type;//个体选择类型
int toursize;//竞赛规模
double bestp;//最好个体选择概率
other_population(int a,int b,int c,int f,int g,double d,double e,int h,double j,int m)
{
popsize=a,pointcnt=b,cross_type=c,mutate_type=f,make_p=g,pc=d,pm=e,toursize=h,bestp=j,select_type=m;
for(int i=0;i<popsize;i++)//初始化种群
{
VI* v=new VI(pointcnt);
for(int j=0;j<pointcnt;j++)
(*v)[j]=j;
random_shuffle(v->begin(),v->end());
pop.PB(MP(fitness(*v,pointcnt),v));
}
sort(pop.begin(),pop.end(),pair_dec);
bestofpop.first=pop[0].first;//初始时最好个体的适应度
bestofpop.second=new VI(*pop[0].second);//初始时最好个体的染色体
}
~other_population()
{
for(int i=0;unsigned(i)<pop.size();i++)
delete pop[i].second;
delete bestofpop.second;
}
void next()//产生下一代种群
{
vector<double> ps(popsize);
if(make_p==0) //按适应度比例分配个体的选择概率
{
double sum=0;
for(int i=0;i<popsize;i++)
sum+=pop[i].first;//计算种群的适应度和
for(int i=0;i<popsize;i++)
ps[i]=pop[i].first/sum;
}
if(make_p==1)//线性排序
{
for(int i=0;i<popsize;i++)
ps[i]=(200-2*i)/popsize*(popsize+1);
}
if(select_type==0)//轮盘赌选择个体
{
vector<pair<double,VI*> > select_res;
vector<double> addsum(popsize);
for(int i=0;i<popsize-1;i++)//计算个体的累计概率
{
if(i==0)
addsum[i]=ps[0];
else
addsum[i]=addsum[i-1]+ps[i];
}
addsum[popsize-1]=1;//1.5;
for(int i=0;i<popsize;i++)
{
double rd=next_double();
int r=lower_bound(addsum.begin(),addsum.end(),rd)-addsum.begin();
VI* v=new VI(*pop[r].second);
select_res.PB(MP(fitness(*v,pointcnt),v));
}
for(int i=0;i<popsize;i++)
delete pop[i].second;
pop=select_res;
}
for(int cc=0;cc<popsize/2;cc++)//随机选择两个个体,然后进行交叉
{
int a=next_int()%popsize;
int b=(a+1+(next_int()%(popsize-1)))%popsize;
if(next_double()<pc)//随机数小于交叉概率,进行交叉
{
if(cross_type==0)//pmx交叉
pmx(*pop[a].second,*pop[b].second,pointcnt);
pop[a].first=fitness(*pop[a].second,pointcnt);//计算交叉后个体a的适应度
if(bestofpop.first<pop[a].first)//更新最好个体
{
bestofpop.first=pop[a].first;
delete bestofpop.second;
bestofpop.second=new VI(*pop[a].second);
}
pop[b].first=fitness(*pop[b].second,pointcnt);//计算交叉后个体b的适应度
if(bestofpop.first<pop[b].first)//更新最好个体
{
bestofpop.first=pop[b].first;
delete bestofpop.second;
bestofpop.second=new VI(*pop[b].second);
}
}
}
for(int i=pop.size()-1;i>=0;i--)//进行变异
if(next_double()<pm)//随机数小于变异概率,进行变异
{
mutate(*pop[i].second,mutate_type,pointcnt);//变异
pop[i].first=fitness(*pop[i].second,pointcnt);//计算变异后个体的适应度
}
sort(pop.begin(),pop.end(),pair_dec);//从大到小排序
if(bestofpop.first<pop[0].first)//更新最好个体
{
delete bestofpop.second;
bestofpop.first=pop[0].first;
bestofpop.second=new VI(*pop[0].second);
}
}
};
int main()
{
srand((unsigned)time(NULL));
int CASNUM,POINTCNT,POPSIZE,GENERATIONS;
//scanf("%d",&CASNUM);//输入实验次数
CASNUM=10;//输入实验次数
cout << "实验次数:" << CASNUM << "次" << endl;
//scanf("%d%d%d",&POINTCNT,&POPSIZE,&GENERATIONS);//输入染色体长度(城市数),种群规模,最大迭代步数
POINTCNT=30;//输入染色体长度(城市数)
POPSIZE=100,GENERATIONS=100;//输入种群规模,最大迭代步数
x.resize(POINTCNT);
y.resize(POINTCNT);
// x[0]=0, x[1]=1.1,x[2]=3.5,x[3]=3,x[4]=7,x[5]=8,x[6]=4,x[7]=4.5,x[8]=9,x[9]=2;
//x[10]=10, x[11]=11.1,x[12]=13.5,x[13]=13,x[14]=17,x[15]=18,x[16]=14,x[17]=14.5,x[18]=19,x[19]=12;
// y[0]=1.1,y[1]=3,y[2]=2,y[3]=4,y[4]=5.1,y[5]=8,y[6]=4,y[7]=4.5,y[8]=9,y[9]=2;
//y[10]=11.1,y[11]=13,y[12]=12,y[13]=14,y[14]=15.1,y[15]=18,y[16]=14,y[17]=14.5,y[18]=19,y[19]=12;
x[0]=41, x[1]=37,x[2]=54,x[3]=25,x[4]=7,x[5]=2,x[6]=68,x[7]=71,x[8]=54,x[9]=83;
y[0]=94,y[1]=84,y[2]=67,y[3]=62,y[4]=64,y[5]=99,y[6]=58,y[7]=44,y[8]=62,y[9]=69;
x[10]=64,x[11]=18,x[12]=22,x[13]=83,x[14]=91,x[15]=25,x[16]=24,x[17]=58,x[18]=71,x[19]=74;
y[10]=60,y[11]=54,y[12]=60,y[13]=46,y[14]=38,y[15]=38,y[16]=42,y[17]=69,y[18]=71,y[19]=78;
x[20]=87,x[21]=18,x[22]=13,x[23]=82,x[24]=62,x[25]=58,x[26]=45,x[27]=41,x[28]=44, x[29]=4;
y[20]=76,y[21]=40,y[22]=40,y[23]=7,y[24]=32,y[25]=35,y[26]=21,y[27]=26,y[28]=35; y[29]=50;
cout<<"城市数="<<POINTCNT<<endl;
cout<<"各城市坐标:"<<endl;
//srand((unsigned)time(NULL));
/* for(int i=10;i<POINTCNT;i++)
{
x[i]=next_int()%1000;y[i]=next_int()%1000;
}*/
for(int i=0;i<POINTCNT;i++)
{
//scanf("%lf%lf",&x[i],&y[i]);//输入各个城市的坐标
cout<<"["<<x[i]<<", "<<y[i]<<"]"<<endl;//输出各个城市的坐标
}
cout<<"染色体长度:"<<POINTCNT<<endl;
cout<<"最大迭代步数:"<<GENERATIONS<<endl;
cout<<"种群规模:"<<POPSIZE<<endl;
int select_type,make_p_type,k,cross_type,mutate_type;
double q,pc,pm;
select_type=0,make_p_type=1,k=5;//输入个体选择方法类型,个体选择概率分配类型,竞赛规模
q=0.5,pc=0.8,pm=0.8;//输入最好个体选择概率,交叉概率,变异概率
cross_type=0,mutate_type=0;//输入交叉类型,变异类型
cout<<"交叉概率:"<<pc<<endl;
cout<<"变异概率"<<pm<<endl;
cout<<"选择操作:按适应度比例分配个体的选择概率,轮盘赌选择个体"<<endl;
cout<<"交叉操作:PMX交叉"<<endl;
cout<<"变异操作:两点互换"<<endl;
double best=1e9,worst=0,sum=0;
VI res;
clock_t start_time;
start_time=clock();
cout << endl;
cout << "正在计算中......" << endl;
for(int cas=0;cas<CASNUM;cas++)//
{
other_population gen(POPSIZE,POINTCNT,cross_type,mutate_type,make_p_type,pc,pm,k,q,select_type);
for(int g=0;g<GENERATIONS;g++)//进行迭代进化
gen.next();
if(best>1.0/gen.bestofpop.first)//更新最好适应度
{
best=1.0/gen.bestofpop.first;
res=*gen.bestofpop.second;//存放最好个体的染色体
}
if(worst<1.0/gen.bestofpop.first)//更新最差适应度
worst=1.0/gen.bestofpop.first;
sum+=1.0/gen.bestofpop.first;//计算各次最好个体的适应度之和
}
cout << endl;
cout << CASNUM << "次遗传算法求解的结果如下:" << endl;
clock_t end_time=clock();
double durTime=double(end_time-start_time);
sum/=CASNUM;//计算平均适应度
cout<<"最好适应度:"<<best<<"\n"<<"最差适应度:"<<worst<<"\n"<<"平均适应度:"<<sum<<"\n";
cout<<"输出最好解:";
for(int i=0;i<POINTCNT;i++)//输出解
{
cout<<res[i];//输出各城市
if (i<POINTCNT-1)
cout<<"-";
}
cout<<endl;
cout<<"平均运行时间:"<<durTime/CASNUM<<"s"<<endl;
cout<<endl;
return 0;
}