蚁群算法解决车间调度问题
關(guān)于蟻群算法:
蟻群系統(tǒng)(Ant System或Ant Colony System)是由意大利學(xué)者Dorigo、Maniezzo等人于20世紀(jì)90年代首先提出來的。他們在研究螞蟻覓食的過程中,發(fā)現(xiàn)單個(gè)螞蟻的行為比較簡單,但是蟻群整體卻可以體現(xiàn)一些智能的行為。例如蟻群可以在不同的環(huán)境下,尋找最短到達(dá)食物源的路徑。這是因?yàn)橄伻簝?nèi)的螞蟻可以通過某種信息機(jī)制實(shí)現(xiàn)信息的傳遞。后又經(jīng)進(jìn)一步研究發(fā)現(xiàn),螞蟻會(huì)在其經(jīng)過的路徑上釋放一種可以稱之為“信息素”的物質(zhì),蟻群內(nèi)的螞蟻對“信息素”具有感知能力,它們會(huì)沿著“信息素”濃度較高路徑行走,而每只路過的螞蟻都會(huì)在路上留下“信息素”,這就形成一種類似正反饋的機(jī)制,這樣經(jīng)過一段時(shí)間后,整個(gè)蟻群就會(huì)沿著最短路徑到達(dá)食物源了。
圖的生成:
車間調(diào)度問題我們可以轉(zhuǎn)換為近似于最大流問題。任務(wù)當(dāng)中的每一個(gè)階段,都是這個(gè)圖當(dāng)中的一個(gè)節(jié)點(diǎn)。我們新增一個(gè)超級(jí)源點(diǎn),超級(jí)源點(diǎn)和所有任務(wù)的第一階段相連。其他的節(jié)點(diǎn),當(dāng)同時(shí)滿足屬于同一任務(wù)的兩個(gè)節(jié)點(diǎn)中間不跳躍階段的條件下相連。
圖的遍歷:
初始情況下,將螞蟻統(tǒng)一放置到超級(jí)源點(diǎn),并且將整個(gè)圖的所有路徑上的信息素設(shè)為一個(gè)固定值。之后,所有螞蟻一起向終點(diǎn)行動(dòng),螞蟻會(huì)受到信息素的影響,螞蟻選擇路徑的方式是螞蟻當(dāng)前可走路徑的信息素加和,作為取隨機(jī)數(shù)m的最大值,通過隨機(jī)數(shù)m和可選信息素,計(jì)算出螞蟻選擇的路徑。當(dāng)所有螞蟻都走到終點(diǎn)的時(shí)候,將全圖的信息素按照信息素消散參數(shù)進(jìn)行消散,并計(jì)算出這些螞蟻的路徑。這個(gè)路徑一種工件加工的順序,按照這個(gè)順序計(jì)算出工件加工的時(shí)間T。通過這個(gè)時(shí)間,計(jì)算出這個(gè)螞蟻新增的信息素W=Q/T(Q是一個(gè)常數(shù))。這個(gè)螞蟻之前經(jīng)歷過的路徑上的信息素都加上W。當(dāng)所有的螞蟻的信息素全部新增到圖當(dāng)中的時(shí)候。將所有螞蟻再放回到起點(diǎn),重復(fù)之前的步驟,隨著重復(fù)次數(shù)的增多,螞蟻會(huì)越來越向著最優(yōu)解靠近。
最優(yōu)解的尋找:
在計(jì)算螞蟻行走的路徑過程中,會(huì)時(shí)刻記錄著當(dāng)前出現(xiàn)過的,工件加工時(shí)間最短的情況。在程序結(jié)束之后,把最短的加工時(shí)間輸出出來。
#include<bits/stdc++.h> #define MAXN 60 //最大工作量 #define INIT_PRE 3000//道路初始信息素量 #define K 2000 //循環(huán)次數(shù) #define DIS 0.5 //信息素消散速率 #define SUPER_START 48 using namespace std; int totalStep; int Step[MAXN]; int phe[MAXN][MAXN][MAXN][MAXN]; int n,m; struct Pair {int i,j;void get(int a,int b){i=a;j=b;} }Jobnum[MAXN]; struct Job {int machine;int len; }job[MAXN][MAXN]; struct Ant {int JobStep[MAXN]; //任務(wù)已運(yùn)行步數(shù)int path[MAXN];int pathlen;int getFullPath(){int sum=0;for (int i=0;i<pathlen;i++)sum+=path[i];return sum;}Pair paths[MAXN]; }; void init() {//totalStep=0;memset(phe,0,sizeof(phe));for (int i=0;i<totalStep;i++)for (int j=0;j<totalStep;j++)for (int k=0;k<totalStep;k++)for (int l=0;l<totalStep;l++)phe[i][j][k][l]=INIT_PRE;for (int i=0;i<totalStep;i++)for (int j=0;j<totalStep;j++)phe[SUPER_START][SUPER_START][i][j]=INIT_PRE;return; } void Dissipation() {for (int i=0;i<totalStep;i++)for (int j=0;j<totalStep;j++)for (int k=0;k<totalStep;k++)for (int l=0;l<totalStep;l++)phe[i][j][k][l] *= DIS;for (int i=0;i<totalStep;i++)for (int j=0;j<totalStep;j++)phe[SUPER_START][SUPER_START][i][j]*= DIS;return; } struct Recording {int start;int ed;int job;int machine; }; int timeCalcu(int Job[], bool draw) {int sum=0;int machineWorkTime[MAXN];int JobLast[MAXN];int JobStep[MAXN];Recording rec[MAXN];memset(machineWorkTime,0,sizeof(machineWorkTime));memset(JobLast,0,sizeof(JobLast));memset(JobStep,0,sizeof(JobStep));memset(rec,0,sizeof(rec));for (int k = 0; k < totalStep; k++){int i = Job[k];rec[k].start = max(JobLast[i],machineWorkTime[job[i][JobStep[i]].machine]);rec[k].job = i;rec[k].ed = rec[k].start + job[i][JobStep[i]].len;JobLast[i] = rec[k].ed;rec[k].machine = job[i][JobStep[i]].machine;machineWorkTime[job[i][JobStep[i]].machine] = rec[k].ed;JobStep[i]++;}for (int i = 0; i < m; i++){sum = max(sum,machineWorkTime[i]);}if (draw == true){int gantt[MAXN][MAXN];memset(gantt,0,sizeof(gantt));for (int i=0;i<totalStep;i++){for (int j=rec[i].start;j<rec[i].ed;j++){gantt[rec[i].machine][j]=rec[i].job+1;}}for (int i=0;i<m;i++)for (int j=0;j<sum;j++)printf("%d%c",gantt[i][j],j==sum-1?'\n':' ');}return sum; } int main() {while (~scanf("%d%d",&n,&m)){totalStep = 0;for (int i=0;i<n;i++){scanf("%d",&Step[i]);totalStep+=Step[i];for (int j=0;j<Step[i];j++){scanf("%d%d",&job[i][j].machine,&job[i][j].len);}}init();int antnum=totalStep*2;Ant ant[antnum+5];Ant bestAnt;int bstime = 999999;for (int sl=0;sl<10;sl++){//printf("%d/10\n",sl);srand(time(0));memset(ant,0,sizeof(ant));for (int i=0;i<antnum;i++)//第i只螞蟻的旅程{//printf("sl=%d/%d\n",i,antnum);int nowJob=SUPER_START; //作為圖的超級(jí)源點(diǎn)ant[i].JobStep[nowJob]=SUPER_START;for (int j=0;j<totalStep;j++){int allpre=0;for (int k=0;k<m;k++){//printf("i:%d j:%d k:%d l:%d ant:%d\n",nowJob,ant[i].JobStep[nowJob],k,ant[i].JobStep[k],i);if (ant[i].JobStep[k]==Step[k]) continue;allpre += phe[nowJob][ ant[i].JobStep[nowJob] ][k][ ant[i].JobStep[k] ];}//printf("%d\n",allpre);int randSelectNum = rand()*rand() % allpre;//printf("OK\n");//printf("搖到的數(shù)字是:%d\n",randSelectNum);int select=0;while (randSelectNum>=0){if (ant[i].JobStep[select]==Step[select]) {select++;continue;}randSelectNum -= phe[nowJob][ ant[i].JobStep[nowJob] ][select][ ant[i].JobStep[select] ];select++;}select--;//printf("螞蟻選擇了%d\n",select);//螞蟻選中的任務(wù)ant[i].path[ant[i].pathlen]=select;ant[i].paths[ant[i].pathlen++].get(select,ant[i].JobStep[select]);ant[i].JobStep[select]++;nowJob = select;//printf("選擇任務(wù)%d 階段%d\n",select,ant[i].JobStep[select]);}}Dissipation(); //每次螞蟻行走完后,信息素都會(huì)消散for (int i = 0; i < antnum; i++){int ans = timeCalcu(ant[i].path,false);if (ans<bstime && totalStep<=ans){bstime = ans;bestAnt = ant[i];}int reward = 2000/ans; //答案越小,獎(jiǎng)勵(lì)越多。for (int j=0;j<ant[i].pathlen-1;j++){int a = ant[i].paths[j].i;int b = ant[i].paths[j].j;int c = ant[i].paths[j+1].i;int d = ant[i].paths[j+1].j;phe[a][b][c][d] += reward;}}//if (sl==1999)/*for (int i = 0; i < antnum; i++){for (int j=0; j<ant[i].pathlen; j++){printf("%d%c",ant[i].path[j]+1,j==ant[i].pathlen-1?'\n':' ');}printf("\n%d\n",timeCalcu(ant[i].path,true));}*/}printf("bestTime:%d\n",bstime);printf("甘特圖:\n");timeCalcu(bestAnt.path,true);printf("加工順序?yàn)?#xff1a;");for (int i=0;i<totalStep;i++)printf("%d%s",bestAnt.path[i]+1,i==totalStep-1?"\n":"->");/*int a[10] = {1,2,1,0,2,1,0,0};timeCalcu(a,true);*/return 0;} }運(yùn)行結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的蚁群算法解决车间调度问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 职工线上健步走活动小程序方案,通过微信小
- 下一篇: 青龙面板+Ninja的企业微信通知设置以