GA算法-R语言实现

GA算法-R语言实现

 

旅行商问题

班共有30位同学,来自22个地区,我们希望在假期来一次说走就走的旅行,将所有同学的家乡走一遍。算起来,路费是一笔很大的花销,所以希望设计一个旅行方案,确保这一趟走下来的总路程最短。

旅行商问题是一个经典的NP问题

NP就是Non-deterministic Polynomial,即多项式复杂程度的非确定性问题,是世界七大数学难题之一。

如果使用枚举法求解,22个地点共有:
(22-1)!/2 = 25545471085854720000 种路线方案

GA算法

遗传算法将“优胜劣汰,适者生存”的生物进化原理引入优化参数形成的编码串联群体中,按所选择的适应度函数并通过遗传中的复制、交叉及变异对个体进行筛选,使适应度高的个体被保留下来,组成新的群体,新的群体既继承了上一代的信息,又优于上一代。这样周而复始,群体中个体适应度不断提高,直到满足一定的条件。遗传算法的算法简单,可并行处理,并能到全局最优解。

GA算法设计

1.生成原始染色体种群

采用实数编码,以N个城市的序号作为一条可能的路径。 例如对8个城市,可生成如下的染色体代表一条路径,8,6,4,2,7,5,3,1.重复操作生成数目等于n的染色体种群。

2.生成适应度函数

由于是求最短路径,适应度函数一般求函数最大值,所以取路径总长度T的倒数,即fitness=1/T。

3.选择染色体

采用轮盘赌的方式产生父代染色体。

4.对染色体种群进行编码

假设有一个含有九个城市的列表:W=(A,B,C,D,E,F,G,H,I)。
有如下两条路线:
W1=(A,D,B,H,F,I,G,E,C)
W2=(B,C,A,D,E,H,I,F,G)
则这两条路线可编码为:
W1=(142869753)
W2=(231458967)

5.交叉

以概率Pc选择参加交叉的个体(偶数个),用两点交叉算子进行操作。
例如对于下面两个染色体个体
(1 3 4 | 5 2 9 | 8 6 7)
(1 7 6 | 9 5 2 | 4 3 8)
通过两点交叉可得到子代染色体为
(1 3 4 | 9 5 2 | 8 6 7)
(1 7 6 | 5 2 9 | 4 3 8)

6.变异

以概率Pm选择参加变异的个体,用对换变异进行操作。随机的选择个体中的两个位点,进行交换基因。
如A=123456789;如果对换点为4和7,则经过对换后为B=123756489

7.解码

对染色体进行解码,恢复染色体的实数表示方法。

8.逐代进化

根据得出的新的染色体,再次返回选择染色体的步骤,进行迭代,直到达到迭代次数,算法停止。

算法实现

#加载packages
library(sp)
library(maptools)
library(geosphere)

source("C:\\Users\\ShangFR\\Desktop\\路径优化\\GA算法脚本.R")
data=read.csv("C:\\Users\\ShangFR\\Desktop\\路径优化\\143地理坐标.csv") #读取城市经纬度数据
border <- readShapePoly("C:\\Users\\ShangFR\\Desktop\\路径优化\\map\\bou2_4p.shp") #读取各省的边界数据等

#初始化(列出地区距离矩阵-聚类)
da=data[,1:2]
rownames(da)=data[,3]
hc=hclust(dist(da))
cutree(hc, h = 10)
plot(hc)

route=CreatDNA(data,5)  
x = route[,1]
y = route[,2]
z = route[,3]
cols=route[,4]

muer.lonlat = cbind(route[,1],route[,2]) # matrix

muer.dists = distm(muer.lonlat, fun=distVincentyEllipsoid) # 精确计算,椭圆 ans=round(muer.dists/1000,2) roundots = list(x=x,y=y,ans=ans,z=z,cols=cols) species = GA4TSP(dots=roundots,initDNA=NULL,N=50,cp=0.1,vp=0.01,maxIter=1000,maxStay=100,maxElite=2,drawing=TRUE)
#粗糙地计算总路程上界
UpperBound  =  function(disM)
{
     mx  =  apply (disM, 1 , max )   #两城市间最长距离
     return sum (mx) )        #最长旅行路径
}
 
#生成随机染色体
rndDNA  =  function(n)
{
     return ( seq( 1 ,n, 1 ) )   #随机生成n条旅行路径
}
 
#对一个解计算总路程的距离
calcScores  =  function(dna,disM)
{
     =  length(dna)          #城市总数
     tmp  =  cbind(dna[ 1 :n],c(dna[ 2 :n],dna[ 1 ]))  #生成起始点城市
     len  =  apply (tmp, 1 ,function(x) disM[x[ 1 ],x[ 2 ]])
     len  =  sum ( len )
     return ( len )       #返回此条旅行路径总距离
}
 
#根据每条染色体的分数计算权重,并以此抽样
roller  =  function(scores,k)
{
     scores  =  max (scores) - scores + 1
     props  =  scores / sum (scores)
     =  length(scores)
     mxind  =  which. max (scores) #保留最优染色体
     ans  =  sample(( 1 :N)[ - mxind],k - 1 ,replace  =  F,prob  =  props[ - mxind])
     return (c(mxind,ans))
}
 
#种群中的繁殖过程
crossEvolve  =  function(i,nGroup,crossGroup,prop)
{
     =  nGroup[i,]
     =  crossGroup[i,]
     =  length(a)
     =  max ( 1 ,trunc(n * prop))
 
     tmpa  =  a
 
     st  =  sample( 1 :n, 1 )
     ind  =  st:(st + m)       #indication 指示、索引
     if  (st + m>n)
     {
         bind  =  which(ind>n)
         ind[bind]  =  ind[bind]  % %  +  1
     }
     cross  =  intersect(b,a[ind])
     tmpa[ind]  =  cross
     return (tmpa)
}
 
#染色体的自我变异
selfVariation  =  function(dna,prop)
{
     =  length(dna)
     pos  =  which(runif(n)
     if  (length(pos) = = 0 )
         return (dna)
     pos  =  sample(pos, 1 )
     newind  =  sample(( 1 :n)[ - pos], 1 )
 
     if  (pos>newind)
     {
         tmp  =  dna[newind:n]
         tmp  =  tmp[ - (pos - newind + 1 )]
         dna[newind]  =  dna[pos]
         dna[(newind + 1 ):n]  =  tmp
     }
     else
     {
         tmp  =  dna[ 1 :newind]
         tmp  =  tmp[ - pos]
         dna[newind]  =  dna[pos]
         dna[ 1 :(newind - 1 )]  =  tmp
     }
     return (dna)
}
 
#以某条染色体代表的解做图
drawIt  =  function(dots,dna,xlab = NULL,ylab = NULL,main = NULL,sub = NULL,col = NULL)
{
#win.graph(width=800, height=800, pointsize=12)
 
     =  dots[[ 1 ]]
     =  dots[[ 2 ]]
       =  dots[[ 4 ]]
       cols = dots[[ 5 ]] + 10
     if  ( is .null(main))
     {
         scores  =  calcScores(dna,dots[[ 3 ]])
#画地图
  plot(border,border = "#BBFFFF" ,col = "#FF7F00" ,ylim  =  c( 18 54 ), panel.first  =  grid(),
       main = paste( "总路程" ,scores, "公里" ),xlab = "经度" ,ylab = "纬度" ,sub = paste( '优化结束-第' ,sub, '代' ));
#增加省会城市坐标点
            points(x,y,pch = 19 ,col = cols)
            text(x,y,z,pos = 1 ,cex = 0.5 )
       =  length(dna)
     for  (i  in  1 :(n - 1 )){ 
       Sys.sleep( 0.3 )
       lines(x[dna[i:(i + 1 )]],y[dna[i:(i + 1 )]],col = "#00FFFF" ,lwd = 3 )}
     lines(x[dna[c(n, 1 )]],y[dna[c(n, 1 )]],col = "#00FFFF" ,lwd = 3 )
 
     }
     else {
 
#画地图
plot(border,border = "#BBFFFF" ,col = "#FF7F00" ,ylim  =  c( 18 54 ),main = paste( "总路程" ,main, "公里" ),
      xlab = "经度" ,ylab = "纬度" ,sub = paste( '第' ,sub, '代' ))
points(x,y,pch = 19 ,col = cols)
if (sub = = 1 )Sys.sleep( 5 )
else {
 
       =  length(dna)
     for  (i  in  1 :(n - 1 )) 
       lines(x[dna[i:(i + 1 )]],y[dna[i:(i + 1 )]],col = "#00FFFF" ,lwd = 3 )
     lines(x[dna[c(n, 1 )]],y[dna[c(n, 1 )]],col = "#00FFFF" ,lwd = 3 )
}}}
 
 
#Genetic Algorithm for Traveller Salesman Problem
GA4TSP  =  function(dots,initDNA = NULL,N,cp,vp,maxIter,maxStay,maxElite,drawing)
{
     disM  =  dots[[ 3 ]]
     =  nrow(disM)
     if  (N  % % 2  > 0 )
         =  N + 1
     Group  =  t(sapply(rep(n,N),rndDNA))
     
       if  (! is .null(initDNA)) Group[ 1 ,] = initDNA
         
     maxL  =  UpperBound(disM)
     stopFlag  =  FALSE
     iterCount  =  1
     stayCount  =  0
     allBest  =  maxL
     eliteBest  =  maxL
     elite  =  mat. or .vec(maxElite,n)
     elitecount  =  0
     eracount  =  0
 
     LastEra  =  maxL
     outputRecorder  =  NULL
     GenerationRecorder  =  NULL
     showScore = FALSE
     eliteInto = FALSE
     #初始化结束
     
     while  (!stopFlag)
     {
         cat( 'Generation:' ,iterCount, 'Era:' ,eracount, 'Elite:' ,elitecount)
         scores  =  apply (Group, 1 ,calcScores,disM)
         bestScore  =  min (scores)
         mind  =  which. min (scores)
         bestDNA  =  Group[mind,] #记录最佳染色体
 
         #更新时代、精英的信息
         if  (bestScore
         {
             stayCount  =  0
             eliteBest  =  bestScore
             eliteDNA  =  bestDNA
             if  (eliteBest
             {
                 allBest  =  eliteBest
                 allDNA  =  eliteDNA
                 outputRecorder  =  rbind(outputRecorder,allDNA)
                 GenerationRecorder  =  c(GenerationRecorder,iterCount)
                 if  (drawing)
                     drawIt(dots,allDNA,main = as.character(allBest),sub = iterCount)
             }
         }
         else
             stayCount  =  stayCount + 1
 
         if  (stayCount  = =  maxStay)
         {
             stayCount  =  0
             eliteBest  =  maxL
             elitecount  =  elitecount + 1
             elite[elitecount,]  =  eliteDNA
             scores  =  apply (Group, 1 ,calcScores,disM)
             =  which(scores  = =  min (scores))
             nind  =  sample(( 1 :N)[ - a],length(a))
             Group[a,]  =  Group[nind,]
             eliteInto  = TRUE
             scores  =  apply (Group, 1 ,calcScores,disM)
             bestScore  =  min (scores)
             mind  =  which. min (scores)
             bestDNA  =  Group[mind,]
         }
 
         if  (elitecount = = maxElite)
         {
             Group[ 1 :elitecount,] = elite
             elite  =  mat. or .vec(maxElite,n)
             elitecount  =  0
             stayCount  =  0
             eliteBest  =  maxL
             eracount  =  eracount + 1
             maxStay  =  maxStay  +  20
             showScore = TRUE
             scores  =  apply (Group, 1 ,calcScores,disM)
             bestScore  =  min (scores)
             mind  =  which. min (scores)
             bestDNA  =  Group[mind,]
         }
         
         #对种群计算分数,产生繁殖与变异
         succind  =  roller(scores,N / 2
         nGroup  =  Group[succind,]           #取最优和一半高权重优秀基因
         crossind  =  sample(succind,N / 2 )
         crossGroup  =  Group[crossind,]      #取最优和一半高权重优秀基因,打乱顺序
         crossans  =  t(sapply( 1 :(N / 2 ),crossEvolve,nGroup,crossGroup,cp))
         crossGroup  =  rbind(nGroup,crossans)
 
         Group  =  t( apply (crossGroup, 1 ,selfVariation,vp))
         if  (eliteInto)
             eliteInto  =  FALSE
         else
             Group[ 1 ,]  =  bestDNA  
 
         stopFlag  =  (iterCount> = maxIter)
        iterCount  =  iterCount + 1
         cat( ' Best:' ,bestScore, 'All:' ,allBest, 'Stay:' ,paste(stayCount, '/' ,maxStay,sep = ' '),' \n')
         if  (showScore)
         {
             scores  =  apply (Group, 1 ,calcScores,disM)
             show(scores[ 1 :(N / 2 )])
             show(scores[(N / 2 + 1 ):(N)])
             #Sys.sleep(1)
             showScore = FALSE
         }
     }
     if  (drawing)
         drawIt(dots,allDNA,sub = maxIter)
  return ( list (DNA  =  outputRecorder,Generation = GenerationRecorder))
}
 
 
#生成初始染色体
CreatDNA  =  function(data,i)
{
hc = hclust(dist(data[, 1 : 2 ]))
data\(col=cutree(hc, k = i) #k = 1 is trivial
INITDNA=data[order(data\)col),]
rownames(INITDNA) = NULL
     return (INITDNA)  
}

转载于:https://www.cnblogs.com/zhp2016/p/6005612.html

你可能感兴趣的:(r语言,python,人工智能)