① 蟻群演算法是什麼
蟻群演算法,又稱螞蟻演算法,是一種用來在圖中尋找優化路徑的機率型演算法。 它由Marco Dorigo於1992年在他的博士論文中提出,其靈感來源於螞蟻在尋找食物過程中發現路徑的行為。蟻群演算法是一種模擬進化演算法,初步的研究表明該演算法具有許多優良的性質。針對PID控制器參數優化設計問題,將蟻群演算法設計的結果與遺傳演算法設計的結果進行了比較,數值模擬結果表明,蟻群演算法具有一種新的模擬進化優化方法的有效性和應用價值。
原理
設想,如果我們要為螞蟻設計一個人工智慧的程序,那麼這個程序要多麼復雜呢?首先,你要讓螞蟻能夠避開障礙物,就必須根據適當的地形給它編進指令讓他們能夠巧妙的避開障礙物,其次,要讓螞蟻找到食物,就需要讓他們遍歷空間上的所有點;再次,如果要讓螞蟻找到最短的路徑,那麼需要計算所有可能的路徑並且比較它們的大小,而且更重要的是,你要小心翼翼地編程,因為程序的錯誤也許會讓你前功盡棄。這是多麼不可思議的程序!太復雜了,恐怕沒人能夠完成這樣繁瑣冗餘的程序。
然而,事實並沒有你想得那麼復雜,上面這個程序每個螞蟻的核心程序編碼不過100多行!為什麼這么簡單的程序會讓螞蟻干這樣復雜的事情?答案是:簡單規則的涌現。事實上,每隻螞蟻並不是像我們想像的需要知道整個世界的信息,他們其實只關心很小范圍內的眼前信息,而且根據這些局部信息利用幾條簡單的規則進行決策,這樣,在蟻群這個集體里,復雜性的行為就會凸現出來。這就是人工生命、復雜性科學解釋的規律!那麼,這些簡單規則是什麼呢?
② 哪本python書立有蟻群演算法
簡介
蟻群演算法(ant colony optimization, ACO),又稱螞蟻演算法,是一種用來在圖中尋找優化路徑的機率型演算法。它由Marco Dorigo於1992年在他的博士論文中提出,其靈感來源於螞蟻在尋找食物過程中發現路徑的行為。蟻群演算法是一種模擬進化演算法,初步的研究表明該演算法具有許多優良的性質。針對PID控制器參數優化設計問題,將蟻群演算法設計的結果與遺傳演算法設計的結果進行了比較,數值模擬結果表明,蟻群演算法具有一種新的模擬進化優化方法的有效性和應用價值。
定義
各個螞蟻在沒有事先告訴他們食物在什麼地方的前提下開始尋找食物。當一隻找到食物以後,它會向環境釋放一種揮發性分泌物pheromone (稱為信息素,該物質隨著時間的推移會逐漸揮發消失,信息素濃度的大小表徵路徑的遠近)來實現的,吸引其他的螞蟻過來,這樣越來越多的螞蟻會找到食物。有些螞蟻並沒有像其它螞蟻一樣總重復同樣的路,他們會另闢蹊徑,如果另開辟的道路比原來的其他道路更短,那麼,漸漸地,更多的螞蟻被吸引到這條較短的路上來。最後,經過一段時間運行,可能會出現一條最短的路徑被大多數螞蟻重復著。
解決的問題
三維地形中,給出起點和重點,找到其最優路徑。
程序代碼:
numpy as npimport matplotlib.pyplot as plt%pylabcoordinates = np.array([[565.0,575.0],[25.0,185.0],[345.0,750.0],[945.0,685.0],[845.0,655.0],[880.0,660.0],[25.0,230.0],[525.0,1000.0],[580.0,1175.0],[650.0,1130.0],[1605.0,620.0],[1220.0,580.0],[1465.0,200.0],[1530.0, 5.0],[845.0,680.0],[725.0,370.0],[145.0,665.0],[415.0,635.0],[510.0,875.0],[560.0,365.0],[300.0,465.0],[520.0,585.0],[480.0,415.0],[835.0,625.0],[975.0,580.0],[1215.0,245.0],[1320.0,315.0],[1250.0,400.0],[660.0,180.0],[410.0,250.0],[420.0,555.0],[575.0,665.0],[1150.0,1160.0],[700.0,580.0],[685.0,595.0],[685.0,610.0],[770.0,610.0],[795.0,645.0],[720.0,635.0],[760.0,650.0],[475.0,960.0],[95.0,260.0],[875.0,920.0],[700.0,500.0],[555.0,815.0],[830.0,485.0],[1170.0, 65.0],[830.0,610.0],[605.0,625.0],[595.0,360.0],[1340.0,725.0],[1740.0,245.0]])def getdistmat(coordinates):num = coordinates.shape[0]distmat = np.zeros((52,52))for i in range(num):for j in range(i,num):distmat[i][j] = distmat[j][i]=np.linalg.norm(coordinates[i]-coordinates[j])return distmatdistmat = getdistmat(coordinates)numant = 40 #螞蟻個數numcity = coordinates.shape[0] #城市個數alpha = 1 #信息素重要程度因子beta = 5 #啟發函數重要程度因子rho = 0.1 #信息素的揮發速度Q = 1iter = 0itermax = 250etatable = 1.0/(distmat+np.diag([1e10]*numcity)) #啟發函數矩陣,表示螞蟻從城市i轉移到矩陣j的期望程度pheromonetable = np.ones((numcity,numcity)) # 信息素矩陣pathtable = np.zeros((numant,numcity)).astype(int) #路徑記錄表distmat = getdistmat(coordinates) #城市的距離矩陣lengthaver = np.zeros(itermax) #各代路徑的平均長度lengthbest = np.zeros(itermax) #各代及其之前遇到的最佳路徑長度pathbest = np.zeros((itermax,numcity)) # 各代及其之前遇到的最佳路徑長度while iter < itermax:# 隨機產生各個螞蟻的起點城市if numant <= numcity:#城市數比螞蟻數多pathtable[:,0] = np.random.permutation(range(0,numcity))[:numant]else: #螞蟻數比城市數多,需要補足pathtable[:numcity,0] = np.random.permutation(range(0,numcity))[:]pathtable[numcity:,0] = np.random.permutation(range(0,numcity))[:numant-numcity]length = np.zeros(numant) #計算各個螞蟻的路徑距離for i in range(numant):visiting = pathtable[i,0] # 當前所在的城市#visited = set() #已訪問過的城市,防止重復#visited.add(visiting) #增加元素unvisited = set(range(numcity))#未訪問的城市unvisited.remove(visiting) #刪除元素for j in range(1,numcity):#循環numcity-1次,訪問剩餘的numcity-1個城市#每次用輪盤法選擇下一個要訪問的城市listunvisited = list(unvisited)probtrans = np.zeros(len(listunvisited))for k in range(len(listunvisited)):probtrans[k] = np.power(pheromonetable[visiting][listunvisited[k]],alpha)*np.power(etatable[visiting][listunvisited[k]],alpha)cumsumprobtrans = (probtrans/sum(probtrans)).cumsum()cumsumprobtrans -= np.random.rand()k = listunvisited[find(cumsumprobtrans>0)[0]] #下一個要訪問的城市pathtable[i,j] = kunvisited.remove(k)#visited.add(k)length[i] += distmat[visiting][k]visiting = klength[i] += distmat[visiting][pathtable[i,0]] #螞蟻的路徑距離包括最後一個城市和第一個城市的距離#print length# 包含所有螞蟻的一個迭代結束後,統計本次迭代的若干統計參數lengthaver[iter] = length.mean()if iter == 0:lengthbest[iter] = length.min()pathbest[iter] = pathtable[length.argmin()].()else:if length.min() > lengthbest[iter-1]:lengthbest[iter] = lengthbest[iter-1]pathbest[iter] = pathbest[iter-1].()else:lengthbest[iter] = length.min()pathbest[iter] = pathtable[length.argmin()].()# 更新信息素changepheromonetable = np.zeros((numcity,numcity))for i in range(numant):for j in range(numcity-1):changepheromonetable[pathtable[i,j]][pathtable[i,j+1]] += Q/distmat[pathtable[i,j]][pathtable[i,j+1]]changepheromonetable[pathtable[i,j+1]][pathtable[i,0]] += Q/distmat[pathtable[i,j+1]][pathtable[i,0]]pheromonetable = (1-rho)*pheromonetable + changepheromonetableiter += 1 #迭代次數指示器+1#觀察程序執行進度,該功能是非必須的if (iter-1)%20==0:print iter-1# 做出平均路徑長度和最優路徑長度fig,axes = plt.subplots(nrows=2,ncols=1,figsize=(12,10))axes[0].plot(lengthaver,'k',marker = u'')axes[0].set_title('Average Length')axes[0].set_xlabel(u'iteration')axes[1].plot(lengthbest,'k',marker = u'')axes[1].set_title('Best Length')axes[1].set_xlabel(u'iteration')fig.savefig('Average_Best.png',dpi=500,bbox_inches='tight')plt.close()#作出找到的最優路徑圖bestpath = pathbest[-1]plt.plot(coordinates[:,0],coordinates[:,1],'r.',marker=u'$cdot$')plt.xlim([-100,2000])plt.ylim([-100,1500])for i in range(numcity-1):#m,n = bestpath[i],bestpath[i+1]print m,nplt.plot([coordinates[m][0],coordinates[n][0]],[coordinates[m][1],coordinates[n][1]],'k')plt.plot([coordinates[bestpath[0]][0],coordinates[n][0]],[coordinates[bestpath[0]][1],coordinates[n][1]],'b')ax=plt.gca()ax.set_title("Best Path")ax.set_xlabel('X axis')ax.set_ylabel('Y_axis')plt.savefig('Best Path.png',dpi=500,bbox_inches='tight')plt.close()③ 用螞蟻演算法來實現公交線網優化,誰有源代碼
我只告訴你什麼是螞蟻演算法: 蟻群演算法(ant colony optimization, ACO),又稱螞蟻演算法,是一種用來在圖中尋找優化路徑的機率型技術。它由Marco Dorigo於1992年在他的博士論文中引入,其靈感來源於螞蟻在尋找食物過程中發現路徑的行為。
為什麼小小的螞蟻能夠找到食物?他們具有智能么?設想,如果我們要為螞蟻設計一個人工智慧的程序,那麼這個程序要多麼復雜呢?首先,你要讓螞蟻能夠避開障礙物,就必須根據適當的地形給它編進指令讓他們能夠巧妙的避開障礙物,其次,要讓螞蟻找到食物,就需要讓他們遍歷空間上的所有點;再次,如果要讓螞蟻找到最短的路徑,那麼需要計算所有可能的路徑並且比較它們的大小,而且更重要的是,你要小心翼翼的編程,因為程序的錯誤也許會讓你前功盡棄。這是多麼不可思議的程序!太復雜了,恐怕沒人能夠完成這樣繁瑣冗餘的程序。
然而,事實並沒有你想得那麼復雜,上面這個程序每個螞蟻的核心程序編碼不過100多行!為什麼這么簡單的程序會讓螞蟻干這樣復雜的事情?答案是:簡單規則的涌現。事實上,每隻螞蟻並不是像我們想像的需要知道整個世界的信息,他們其實只關心很小范圍內的眼前信息,而且根據這些局部信息利用幾條簡單的規則進行決策,這樣,在蟻群這個集體里,復雜性的行為就會凸現出來。這就是人工生命、復雜性科學解釋的規律!那麼,這些簡單規則是什麼呢?下面詳細說明:
1、范圍:
螞蟻觀察到的范圍是一個方格世界,螞蟻有一個參數為速度半徑(一般是3),那麼它能觀察到的范圍就是3*3個方格世界,並且能移動的距離也在這個范圍之內。
2、環境:
螞蟻所在的環境是一個虛擬的世界,其中有障礙物,有別的螞蟻,還有信息素,信息素有兩種,一種是找到食物的螞蟻灑下的食物信息素,一種是找到窩的螞蟻灑下的窩的信息素。每個螞蟻都僅僅能感知它范圍內的環境信息。環境以一定的速率讓信息素消失。
3、覓食規則:
在每隻螞蟻能感知的范圍內尋找是否有食物,如果有就直接過去。否則看是否有信息素,並且比較在能感知的范圍內哪一點的信息素最多,這樣,它就朝信息素多的地方走,並且每隻螞蟻多會以小概率犯錯誤,從而並不是往信息素最多的點移動。螞蟻找窩的規則和上面一樣,只不過它對窩的信息素做出反應,而對食物信息素沒反應。
4、移動規則:
每隻螞蟻都朝向信息素最多的方向移,並且,當周圍沒有信息素指引的時候,螞蟻會按照自己原來運動的方向慣性的運動下去,並且,在運動的方向有一個隨機的小的擾動。為了防止螞蟻原地轉圈,它會記住最近剛走過了哪些點,如果發現要走的下一點已經在最近走過了,它就會盡量避開。
5、避障規則:
如果螞蟻要移動的方向有障礙物擋住,它會隨機的選擇另一個方向,並且有信息素指引的話,它會按照覓食的規則行為。
7、播撒信息素規則:
每隻螞蟻在剛找到食物或者窩的時候撒發的信息素最多,並隨著它走遠的距離,播撒的信息素越來越少。
根據這幾條規則,螞蟻之間並沒有直接的關系,但是每隻螞蟻都和環境發生交互,而通過信息素這個紐帶,實際上把各個螞蟻之間關聯起來了。比如,當一隻螞蟻找到了食物,它並沒有直接告訴其它螞蟻這兒有食物,而是向環境播撒信息素,當其它的螞蟻經過它附近的時候,就會感覺到信息素的存在,進而根據信息素的指引找到了食物。
說了這么多,螞蟻究竟是怎麼找到食物的呢?
在沒有螞蟻找到食物的時候,環境沒有有用的信息素,那麼螞蟻為什麼會相對有效的找到食物呢?這要歸功於螞蟻的移動規則,尤其是在沒有信息素時候的移動規則。首先,它要能盡量保持某種慣性,這樣使得螞蟻盡量向前方移動(開始,這個前方是隨機固定的一個方向),而不是原地無謂的打轉或者震動;其次,螞蟻要有一定的隨機性,雖然有了固定的方向,但它也不能像粒子一樣直線運動下去,而是有一個隨機的干擾。這樣就使得螞蟻運動起來具有了一定的目的性,盡量保持原來的方向,但又有新的試探,尤其當碰到障礙物的時候它會立即改變方向,這可以看成一種選擇的過程,也就是環境的障礙物讓螞蟻的某個方向正確,而其他方向則不對。這就解釋了為什麼單個螞蟻在復雜的諸如迷宮的地圖中仍然能找到隱蔽得很好的食物。
當然,在有一隻螞蟻找到了食物的時候,其他螞蟻會沿著信息素很快找到食物的。
螞蟻如何找到最短路徑的?這一是要歸功於信息素,另外要歸功於環境,具體說是計算機時鍾。信息素多的地方顯然經過這里的螞蟻會多,因而會有更多的螞蟻聚集過來。假設有兩條路從窩通向食物,開始的時候,走這兩條路的螞蟻數量同樣多(或者較長的路上螞蟻多,這也無關緊要)。當螞蟻沿著一條路到達終點以後會馬上返回來,這樣,短的路螞蟻來回一次的時間就短,這也意味著重復的頻率就快,因而在單位時間里走過的螞蟻數目就多,灑下的信息素自然也會多,自然會有更多的螞蟻被吸引過來,從而灑下更多的信息素……;而長的路正相反,因此,越來越多地螞蟻聚集到較短的路徑上來,最短的路徑就近似找到了。也許有人會問局部最短路徑和全局最短路的問題,實際上螞蟻逐漸接近全局最短路的,為什麼呢?這源於螞蟻會犯錯誤,也就是它會按照一定的概率不往信息素高的地方走而另闢蹊徑,這可以理解為一種創新,這種創新如果能縮短路途,那麼根據剛才敘述的原理,更多的螞蟻會被吸引過來。
引申:
跟著螞蟻的蹤跡,你找到了什麼?通過上面的原理敘述和實際操作,我們不難發現螞蟻之所以具有智能行為,完全歸功於它的簡單行為規則,而這些規則綜合起來具有下面兩個方面的特點:
1、多樣性
2、正反饋
多樣性保證了螞蟻在覓食的時候不置走進死胡同而無限循環,正反饋機制則保證了相對優良的信息能夠被保存下來。我們可以把多樣性看成是一種創造能力,而正反饋是一種學習強化能力。正反饋的力量也可以比喻成權威的意見,而多樣性是打破權威體現的創造性,正是這兩點小心翼翼的巧妙結合才使得智能行為涌現出來了。
引申來講,大自然的進化,社會的進步、人類的創新實際上都離不開這兩樣東西,多樣性保證了系統的創新能力,正反饋保證了優良特性能夠得到強化,兩者要恰到好處的結合。如果多樣性過剩,也就是系統過於活躍,這相當於螞蟻會過多的隨機運動,它就會陷入混沌狀態;而相反,多樣性不夠,正反饋機制過強,那麼系統就好比一潭死水。這在蟻群中來講就表現為,螞蟻的行為過於僵硬,當環境變化了,螞蟻群仍然不能適當的調整。
既然復雜性、智能行為是根據底層規則涌現的,既然底層規則具有多樣性和正反饋特點,那麼也許你會問這些規則是哪裡來的?多樣性和正反饋又是哪裡來的?我本人的意見:規則來源於大自然的進化。而大自然的進化根據剛才講的也體現為多樣性和正反饋的巧妙結合。而這樣的巧妙結合又是為什麼呢?為什麼在你眼前呈現的世界是如此栩栩如生呢?答案在於環境造就了這一切,之所以你看到栩栩如生的世界,是因為那些不能夠適應環境的多樣性與正反饋的結合都已經死掉了,被環境淘汰了!
參數說明:
最大信息素:螞蟻在一開始擁有的信息素總量,越大表示程序在較長一段時間能夠存在信息素。信息素消減的速度:隨著時間的流逝,已經存在於世界上的信息素會消減,這個數值越大,那麼消減的越快。
錯誤概率表示這個螞蟻不往信息素最大的區域走的概率,越大則表示這個螞蟻越有創新性。
速度半徑表示螞蟻一次能走的最大長度,也表示這個螞蟻的感知范圍。
記憶能力表示螞蟻能記住多少個剛剛走過點的坐標,這個值避免了螞蟻在本地打轉,停滯不前。而這個值越大那麼整個系統運行速度就慢,越小則螞蟻越容易原地轉圈。
-----例子-----
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>蟻群演算法js版</title>
<style>
.ant{
position:absolute;
background-color:#000000;
overflow:hidden;
width:2px;
height:2px;
}
.food{
position:absolute;
background-color:#0000ff;
overflow:hidden;
width:2px;
height:2px;
}
.nest{
position:absolute;
background-color:#ff0000;
overflow:hidden;
width:2px;
height:2px;
}
</style>
<script type="text/javaScript">
//============================
//系統參數初始化
//----------------------------
//生命體數量與軌跡長度
Unit=10;Path=30;
//生命體速度上下限
v0=2;vM=10;
//生命體加速度變化范圍
Kr=0.1;Kv=0.1*(vM-v0);
//生命體運動范圍
x0=0;xM=document.documentElement.clientWidth;
y0=0;yM=document.documentElement.clientHeight;
//生命體出生地(巢穴)
xi0=x0+(xM-x0)*Math.random();
yi0=y0+(yM-y0)*Math.random();
str0='<div class="ant" style="left:'+xi0+';top:'+yi0+';"></div>';
//食物所在地
xf=x0+(xM-x0)*Math.random();
yf=y0+(yM-y0)*Math.random();
//氣味感知范圍
R_2=5*5;
//============================
var r=new Array();
var v=new Array();
var dr=new Array();
var dv=new Array();
var x=new Array();
var y=new Array();
var life=new Array();
//單擊暫停
var xi0,yi0,xf,yf;
var Time0,str0;
window.status='pause';
function document.onclick(){
if(window.status=='pause'){
window.status=0;
nest.style.left=xi0;
nest.style.top=yi0;
food.style.left=xf;
food.style.top=yf;
//測試初始化時間用
Time0=(new Date()).getTime();
init(0);
}else{
window.status='pause';
}
}
//窗口大小調整後刷新頁面以調整系統參數
function window.onresize(){
// window.location.href=document.location;
}
//初始化函數
function init(i){
if(window.status!='pause'&&i<Unit){
if(!life){
document.body.appendChild(life=document.createElement(str0));
x=xi0;
y=yi0;
r=Math.random();
v=1/Math.random();
dr=Kr*Math.random();
dv=Kv*Math.random();
}
Move(i);
window.status=i+1;
setTimeout('init('+(i+1)+')',i);
// }else{
// alert('生成耗時:'+((new Date()).getTime()-Time0)+'ms');
}
}
//運動函數
Total=Unit*Path;
P2=2*Math.PI;
function Move(i){
if(window.status!='pause'){
k=i%Unit;
X=x[k];
Y=y[k];
R=r[k];
V=v[k];
if(!life){
str='<div class="ant" style="left:'+X+';top:'+Y+';"></div>';
document.body.appendChild(life=document.createElement(str));
}
obj=life;
R+=dr[k]*(2*Math.random()-1);
V+=dv[k]*(2*Math.random()-1);
X+=Math.sin(P2*R)*V;
Y+=Math.cos(P2*R)*V;
//遇到食物原路返回並減小角度變化
distance=(X-xf)*(X-xf)+(Y-yf)*(Y-yf);
if(distance<R_2){
R+=0.5;
r/=2;
v*=2;
}
distance=(X-xi0)*(X-xi0)+(Y-yi0)*(Y-yi0);
if(distance<R_2){
R+=0.5;
r/=2;
v*=2;
}
/*----------------------------------
/*================================*/
//碰撞邊界反彈
R=(X<x0||X>xM)?-R:R;
R=(Y<y0||Y>yM)?0.5-R:R;
X=x[k]+Math.sin(P2*R)*V;
Y=y[k]+Math.cos(P2*R)*V;
/*================================*/
//溢出邊界重生(類似流星效果)
if(X<x0||X>xM||Y<y0||Y>yM){
X=xi0;
Y=yi0;
}
/*----------------------------------
/*================================*/
//邊界限制
x[k]=X=(X<x0)?x0:(X>xM)?xM-2:X;
y[k]=Y=(Y<y0)?y0:(Y>yM)?yM-2:Y;
r[k]=R>1?R-1:R<0?R+1:R;
v[k]=V=(V<v0)?v0:((V<vM)?V:vM);
/*================================*/
obj.style.left=x[k]=X;
obj.style.top=y[k]=Y;
setTimeout('Move('+(i+Unit)%Total+')',Unit);
}
}
//根據瀏覽器自動載入動畫
switch(navigator.appName.toLowerCase()){
case "netscape":
window.addEventListener("load",document.onclick,false);
break;
case "microsoft internet explorer":
default:
window.attachEvent("onload",document.onclick);
break;
}
</script>
</head>
<body scroll="no">
<div id="food" class="food"></div>
<div id="nest" class="nest"></div>
</body>
</html>
④ 鋩佺兢綆楁硶鐢ㄤ粈涔堣蔣浠剁畻濂藉憿錛
褰撶劧鏄鐢╩atlab錛屼綘濡傛灉鏈塁璇璦鎴栬匔++鐨勫熀紜錛宮atlab寰堝規槗涓婃墜鐨勶紝鍦ㄥ緢澶氭搷浣滀笂瀹冩瘮VC絳夎蔣浠舵洿濂界敤銆
⑤ 奼侾areto鋩佺兢綆楁硶鐨勬簮浠g爜 Java鐨
璇存槑錛氫俊鎮緔犳潈閲嶏紝璺寰勬潈閲嶅拰淇℃伅緔犺捀鍙戠巼瀵規渶鍚庣殑緇撴灉褰卞搷寰堝ぇ錛岄渶瑕佸井璋冦
鐩鍓嶅彂鐜2 / 5 / 0.5 鑳借揪鍒扮◢寰璁╀漢婊℃剰鐨勬晥鏋溿傛湰紼嬪簭紱誨畬緹庣殑ACO榪樺樊寰堣繙錛屼粎渚涘弬鑰冦
鏈鋩佺兢綆楁硶涓篈S綆楁硶銆
鐢ㄦ硶錛
1.new涓涓瀵硅薄
ACOforTSP tsp = new ACPforTSP(tsp鏁版嵁鏂囦歡鍚,榪浠f℃暟錛岃殏鋩佹暟閲忥紝淇℃伅緔犳潈閲嶏紝璺寰勬潈閲嶏紝淇℃伅緔犺捀鍙戠巼錛;
2.鐢╣o()鏂規硶榪愯
tsp.go();
ACOforTSP.java
___________________________________________________________________
import java.io.File;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
import static java.lang.Math.random;
import java.util.HashMap;
import java.io.FileReader;
import java.io.BufferedReader;
/**
*
* @author dvdface
*/
public class ACOforTSP {
//鍩庡競鐨勮窛紱昏〃
private double[][] distance;
//璺濈葷殑鍊掓暟琛
private double[][] heuristic;
//鍚鍙戜俊鎮琛
private double[][] pheromone;
//鏉冮噸
private int alpha, beta;
//榪浠g殑嬈℃暟
private int iterationTimes;
//鋩傝殎鐨勬暟閲
private int numbersOfAnt;
//钂稿彂鐜
private double rate;
ACOforTSP (String file, int iterationTimes, int numbersOfAnt, int alpha, int beta, double rate) {
//鍔犺澆鏂囦歡
this.initializeData(file);
//鍒濆嬪寲鍙傛暟
this.iterationTimes = iterationTimes;
//璁劇疆鋩傝殎鏁伴噺
this.numbersOfAnt = numbersOfAnt;
//璁劇疆鏉冮噸
this.alpha = alpha;
this.beta = beta;
//璁劇疆钂稿彂鐜
this.rate = rate;
}
private void initializeData(String filename) {
//瀹氫箟鍐呴儴綾
class City {
int no;
double x;
double y;
City(int no, double x, double y) {
this.no = no;
this.x = x;
this.y = y;
}
private double getDistance(City city) {
return sqrt(pow((x - city.x), 2) + pow((y - city.y), 2));
}
}
try {
//瀹氫箟HashMap淇濆瓨璇誨彇鐨勫潗鏍囦俊鎮
HashMap<Integer, City> map = new HashMap<Integer, City>();
//璇誨彇鏂囦歡
BufferedReader reader = new BufferedReader(new FileReader(new File(filename)));
for (String str = reader.readLine(); str != null; str = reader.readLine()) {
//灝嗚誨埌鐨勪俊鎮淇濆瓨鍏HashMap
if (str.matches("([0-9]+)(\\s*)([0-9]+)(.?)([0-9]*)(\\s*)([0-9]+)(.?)([0-9]*)")) {
String[] data = str.split("(\\s+)");
City city = new City(Integer.parseInt(data[0]),
Double.parseDouble(data[1]),
Double.parseDouble(data[2]));
map.put(city.no, city);
}
}
//鍒嗛厤璺濈葷煩闃靛瓨鍌ㄧ┖闂
distance = new double[map.size() + 1][map.size() + 1];
//鍒嗛厤璺濈誨掓暟鐭╅樀瀛樺偍絀洪棿
heuristic = new double[map.size() + 1][map.size() + 1];
//鍒嗛厤淇℃伅緔犵煩闃靛瓨鍌ㄧ┖闂
pheromone = new double[map.size() + 1][map.size() + 1];
for (int i = 1; i < map.size() + 1; i++) {
for (int j = 1; j < map.size() + 1; j++) {
//璁$畻鍩庡競闂寸殑璺濈伙紝騫跺瓨鍏ヨ窛紱葷煩闃
distance[i][j] = map.get(i).getDistance(map.get(j));
//璁$畻璺濈誨掓暟錛屽苟瀛樺叆璺濈誨掓暟鐭╅樀
heuristic[i][j] = 1 / distance[i][j];
//鍒濆嬪寲淇℃伅緔犵煩闃
pheromone[i][j] = 1;
}
}
} catch (Exception exception) {
System.out.println("鍒濆嬪寲鏁版嵁澶辮觸錛");
}
}
class Ant {
//宸茶塊棶鍩庡競鍒楄〃
private boolean[] visited;
//璁塊棶欏哄簭琛
private int[] tour;
//宸茶塊棶鍩庡競鐨勪釜鏁
private int n;
//鎬葷殑璺濈
private double total;
Ant() {
//緇欒塊棶欏哄簭琛ㄥ垎閰嶇┖闂
tour = new int[distance.length+1];
//宸插瓨鍏ュ煄甯傛暟閲忎負n錛屽垰寮濮嬩負0
n = 0;
//灝嗚搗濮嬪煄甯1,鏀懼叆璁塊棶緇撶偣欏哄簭琛ㄧ涓欏
tour[++n] = 1;
//緇欏凡璁塊棶鍩庡競緇撶偣鍒嗛厤絀洪棿
visited = new boolean[distance.length];
//絎涓涓鍩庡競涓哄嚭鍙戝煄甯傦紝璁劇疆涓哄凡璁塊棶
visited[tour[n]] = true;
}
private int chooseCity() {
//鐢ㄦ潵random鐨勯殢鏈烘暟
double m = 0;
//鑾峰緱褰撳墠鎵鍦ㄧ殑鍩庡競鍙鋒斁鍏j,濡傛灉鍜宩鐩擱偦鐨勫煄甯傛病鏈夎璁塊棶錛岄偅涔堝姞鍏m
for (int i = 1, j = tour[n]; i < pheromone.length; i++) {
if (!visited[i]) {
m += pow(pheromone[j][i], alpha) * pow(heuristic[j][i], beta);
}
}
//淇濆瓨闅忔満鍒扮殑鏁
double p = m * random();
//瀵繪壘琚闅忔満鍒扮殑鍩庡競
double k = 0;
//淇濆瓨鎵懼埌鐨勫煄甯
int q = 0;
for (int i = 1, j = tour[n]; k < p; i++) {
if (!visited[i]) {
k += pow(pheromone[j][i], alpha) * pow(heuristic[j][i], beta);
q = i;
}
}
return q;
}
private void constructSolution () {
while (n != (distance.length-1) ) {
//閫夊彇涓嬩竴涓鍩庡競
int p = chooseCity();
//璁$畻鎬葷殑璺濈
total += distance[tour[n]][p];
//灝嗛夊彇鍒扮殑鍩庡競鏀懼叆宸茶塊棶鍒楄〃
tour[++n] = p;
//灝嗛夊彇鍒扮殑鍩庡競鏍囪頒負宸茶塊棶
visited[p] = true;
}
//鍥炲埌璧風偣
total += distance[tour[1]][tour[n]];
//灝嗚搗鐐瑰姞鍏ヨ塊棶欏哄簭琛ㄧ殑鏈鍚
tour[++n] = tour[1];
}
private void releasePheromone() {
//閲婃斁淇℃伅緔犵殑澶у皬
double t = 1/total;
//閲婃斁淇℃伅緔
for (int i=1;i<tour.length-1;i++) {
pheromone[tour[i]][tour[i+1]] += t;
pheromone[tour[i+1]][tour[i]] += t;
}
}
}
public void go() {
//淇濆瓨鏈濂界殑璺寰勫拰璺寰勯暱搴
double bestTotal = Double.MAX_VALUE;
int[] bestTour = new int[distance.length+1];
//鏂板緩鋩傝殎鏁扮粍錛岀敤鏉ュ紩鐢ㄦ墍鍒涘緩鐨勮殏鋩
Ant[] ant = new Ant[numbersOfAnt];
//榪涜宨terationTimes嬈¤凱浠
while (iterationTimes != 0) {
//鍒濆嬪寲鏂扮殑涓鎵硅殏鋩侊紙榪欓噷鐢ㄦ瀯閫犳柊鐨勮殏鋩佷唬鏇塊噸緗鋩傝殎鐘舵侊級
for (int i=0; i<numbersOfAnt; i++) {
ant[i] = new Ant();
}
//榪涜屼竴嬈¤凱浠o紙鍗寵╂墍鏈夌殑鋩傝殎鏋勫緩涓鏉¤礬寰勶級
for (int i=0; i<numbersOfAnt; i++) {
ant[i].constructSolution();
//濡傛灉鋩傝殎鏋勫緩鐨勮礬寰勯暱搴︽瘮涓婃℃渶濂界殑榪樺ソ錛岄偅涔堜繚瀛樿繖涓闀垮害鍜屽畠鎵璧扮殑璺寰
if (ant[i].total<bestTotal) {
bestTotal = ant[i].total;
System.array(ant[i].tour, 1, bestTour, 1, bestTour.length-1);
}
}
//钂稿彂淇℃伅緔
evaporatePheromone();
//閲婃斁淇℃伅緔
for (int i=0; i<numbersOfAnt; i++) {
ant[i].releasePheromone();
}
//鎶ュ憡鏈嬈¤凱浠g殑淇℃伅
System.out.format("鏈嬈′負鍊掓暟絎%d嬈¤凱浠,褰撳墠鏈浼樿礬寰勯暱搴︿負%10.2f\n",iterationTimes,bestTotal);
//榪浠f繪暟鍑忓幓1錛岃繘琛屼笅嬈¤凱浠
iterationTimes--;
}
//杈撳嚭鏈濂界殑璺寰勯暱搴
System.out.format("寰楀埌鐨勬渶浼樼殑璺寰勯暱搴︿負:%10.2f\n",bestTotal);
//杈撳嚭鏈濂界殑璺寰
System.out.println("鏈浼樿礬寰勫備笅錛");
for (int i=1; i<bestTour.length; i++) {
System.out.print("鈫"+bestTour[i]);
}
}
private void evaporatePheromone() {
for (int i = 1; i < pheromone.length; i++)
for (int j = 1; j < pheromone.length; j++) {
pheromone[i][j] *= 1-rate;
}
}
}
⑥ 急求蟻群演算法解決 VRPTW問題的matlab代碼,最好是ACS或者MMAS的!
function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ACATSP(C,NC_max,m,Alpha,Beta,Rho,Q)
%%=========================================================================
%% ACATSP.m
%% Ant Colony Algorithm for Traveling Salesman Problem
%% ChengAihua,PLA Information Engineering University,ZhengZhou,China
%% Email:[email protected]
%% All rights reserved
%%-------------------------------------------------------------------------
%% 主要符號說明
%% C n個城市的坐標,n×2的矩陣
%% NC_max 最大迭代次數
%% m 螞蟻個數
%% Alpha 表徵信息素重要程度的參數
%% Beta 表徵啟發式因子重要程度的參數
%% Rho 信息素蒸發系數
%% Q 信息素增加強度系數
%% R_best 各代最佳路線
%% L_best 各代最佳路線的長度
%% 運行可能要很久,需要耐心等待
%%=========================================================================
n=length(C); %n 為市個數
for i=1:n %坐標矩陣轉換為距離矩陣
for j=1:n
D(i,j)=sqrt((x(i,1)-x(j,1))^2+(x(i,2)-x(j,2))^2);
end
end
for i=1:n %Eta為啟發因子,這里設為距離的倒數
for j=1:n %原文作者少考慮的當D=0是MATLAB提示出錯
if i~=j
Eta(i,j)=1./D(i,j);
end
end
end
for i=1:n
Eta(i,i)=0;
end
Tau=ones(n,n); %Tau為信息素矩陣
Tabu=zeros(m,n); %存儲並記錄路徑的生成
NC=1; %迭代計數器
R_best=zeros(NC_max,n); %各代最佳路線
L_best=inf.*ones(NC_max,1); %各代最佳路線的長度
L_ave=zeros(NC_max,1); %各代路線的平均長度
while NC<=NC_max %停止條件之一:達到最大迭代次數
%%第二步:將m只螞蟻放到n個城市上
Randpos=[];
for i=1:(ceil(m/n))
Randpos=[Randpos,randperm(n)];
end
Tabu(:,1)=(Randpos(1,1:m))';
%%第三步:m只螞蟻按概率函數選擇下一座城市,完成各自的周遊
for j=2:n
for i=1:m
visited=Tabu(i,1:(j-1)); %已訪問的城市
J=zeros(1,(n-j+1)); %待訪問的城市
P=J; %待訪問城市的選擇概率分布
Jc=1;
for k=1:n
if length(find(visited==k))==0
J(Jc)=k;
Jc=Jc+1;
end
end
%下面計算待選城市的概率分布
for k=1:length(J)
P(k)=(Tau(visited(end),J(k))^Alpha)*(Eta(visited(end),J(k))^Beta);
end
P=P/(sum(P));
%按概率原則選取下一個城市
Pcum=cumsum(P);
Select=find(Pcum>=rand);
to_visit=J(Select(1));
Tabu(i,j)=to_visit;
end
end
if NC>=2
Tabu(1,:)=R_best(NC-1,:);
end
%%第四步:記錄本次迭代最佳路線
L=zeros(m,1);
for i=1:m
R=Tabu(i,:);
for j=1:(n-1)
L(i)=L(i)+D(R(j),R(j+1));
end
L(i)=L(i)+D(R(1),R(n));
end
L_best(NC)=min(L);
pos=find(L==L_best(NC));
R_best(NC,:)=Tabu(pos(1),:);
L_ave(NC)=mean(L);
NC=NC+1;
%%第五步:更新信息素
Delta_Tau=zeros(n,n);
for i=1:m
for j=1:(n-1)
Delta_Tau(Tabu(i,j),Tabu(i,j+1))=Delta_Tau(Tabu(i,j),Tabu(i,j+1))+Q/L(i);
end
Delta_Tau(Tabu(i,n),Tabu(i,1))=Delta_Tau(Tabu(i,n),Tabu(i,1))+Q/L(i);
end
Tau=(1-Rho).*Tau+Delta_Tau;
%%第六步:禁忌表清零
Tabu=zeros(m,n);
end
%%第七步:輸出結果
Pos=find(L_best==min(L_best));
Shortest_Route=R_best(Pos(1),:);
Shortest_Length=L_best(Pos(1));
DrawRoute(C,Shortest_Route) %調用函數繪圖