最近在上計算智慧型的課,老師剛剛教了遺傳演算法,布置了用遺傳演算法解決tsp的問題的作業,於是經過幾小時的奮戰,終於編寫完成。
首先先對tsp問題進行分析。tsp問題,也就是旅行商問題,題目的大題內容是 一位旅行商,要遍遊n座城市(城市數量記為num_city), 已知每兩座城市之間的位置,要求每座城市必須去且只去過一次,求遍遊該n座城市的最短路程。
利用遺傳演算法解決該問題,步驟如下:
1.初始化城市之間的距離
2.生成並初始化初始種群,種群內每個個體儲存著一條完整的路徑(每個城市標號出現且只出現一次)
3.計算目前種群每個個體的適應值(要求求最短路程,路徑一定是個正數,故而得到每個個體中儲存的路徑的總路程後,取倒數,得到的數越大,適應性越高,總路程越短)
4.找出目前最優個體,讓其直接複製至下一代(即不變異)
5.對其他個體根據發生交叉互換的概率pc,得到參與交叉互換的個體集合
6.使參與交叉互換的個體隨機發生交叉互換(每個個體只參與一次)交叉互換的片段起始點和終點均隨機產生
7.對除最優個體外的每個個體,根據突變概率pm發生突變,隨機產生兩個位置點,使這兩個位置點之間的片段進行置倒(即2345變成5432)
8.迴圈執行步驟34567,直到演變代數》generations為止(暫定為5000代)
**如下所示,(注釋部分用的printf用於測試查錯,可忽視)
#include #include #include #include #define rand(x) (rand()%(x))
#define num_city (30)
#define generations (5000)
#define max_size (50)
#define lowest_alive (1.0/max_size)
typedef struct _groupgroup;
int citydistance[num_city][num_city];
group g_group[max_size];
float pm = 0.1;
float pc = 0.8;
int bestone;
void getfitness(group &group) // 得到適應值
group.adapt = distance;
group.palive = 1 / (float)distance;
}void swap(int &a, int &b) // 交換ab值
void init() // 初始化
} printf("城市距離如下:\n");
for (int i = 0; i < num_city; i++)
printf("\n");
} for (int i = 0; i < max_size; i++) // 初始化樣本數列 }
int r;
for (int i = 0; i < max_size; i++) // 打亂順序 }
printf("產生初始種群如下:\n");
for (int i = 0; i < max_size; i++)
printf("\n"); }}
void getalivep() // 存活率
for (int i = 0; i < max_size; i++) // 矯正個體存活率 讓總和為1
bestone = 0;
for (int i = 0; i < max_size; i++)
printf("目前最佳個體為:%d, 其距離為%d,其軌跡如下:\n", bestone+1, g_group[bestone].adapt);
for (int i = 0; i < num_city; i++)
printf("%d ", g_group[bestone].city[i]);
printf("\n");
}int isonit(int num, int array[num_city], int ignorepos, int pos1, int pos2) // num是否在array的pos1到pos2之間 其中跳過ignorepos(該數字的原位置)
return -1;
}void swap(int sel1,int sel2,int pos1, int pos2) // 交叉互換
//for (int j = 0; j < num_city; j++)
// printf("%4d", g_group[sel1].city[j]);
//printf("\n");
//for (int j = 0; j < num_city; j++)
// printf("%4d", g_group[sel2].city[j]);
//printf("\n");
int pos;
//printf("開始矯正重複值\n");
int times = 0;
for (int i = 0; i < num_city; i++) // 矯正重複值
do } while (pos != -1);
do} while (pos != -1);
}// printf("交叉互換過程完畢\n");
}void mutation(int sel, int pos1,int pos2)//個體突變
}void genetic() // 產生下一代種群
g_group[minnum] = g_group[maxnum]; // 使最大直接替換最小
//printf("開始交叉\n");
// 交叉配對
int selnum;
int maxtimes = 0, nowtimes = 0;
int canselected[max_size]; // 可以用於交叉的個體
bool iscanselected[max_size];
for (int i = 0; i < max_size; i++) }
for (int i = 0; i < maxtimes; i++)
int pos1, pos2;
for (int i = 0; i < maxtimes; i+=2)
/* printf("%d與%d開始交叉互換\n", canselected[i], canselected[selnum]);*/
swap(canselected[i], canselected[selnum], pos1, pos2);
/*printf("第%d個體與第%d個體進行交叉配對,得到新的兩個個體如下:\n", canselected[i] + 1, canselected[selnum] + 1);
printf("第%d個體:\n", canselected[i] + 1);
for (int j = 0; j < num_city; j++)
printf("%4d", g_group[canselected[i]].city[j]);
printf("\n第%d個體:\n", canselected[selnum] + 1);
for (int j = 0; j < num_city; j++)
printf("%4d", g_group[canselected[selnum]].city[j]);
printf("\nselnum:%d, maxtimes:%d\n",selnum,maxtimes);*/
}/*printf("開始突變\n");*/
// 突變
for (int i = 0; i < max_size; i++)
if (rand(100) / 100.0 < pm) // 符合突變概率
/*printf("第%d個體突變前:\n", i + 1);
for (int j = 0; j < num_city; j++)
printf("%4d", g_group[i].city[j]);
printf("\n");*/
mutation(i, pos1, pos2);
// printf("第%d個體突變:\n", i + 1);/*
// for (int j = 0; j < num_city; j++)
// printf("%4d", g_group[i].city[j]);
// printf("\n");
} }}void train()
while (nowgenerations < generations);
printf("經過%d次繁衍,得到的優秀個體為:\n", nowgenerations);
printf("其距離為%d,其軌跡如下:\n", g_group[bestone].adapt);
for (int i = 0; i < num_city; i++)
printf("%d ", g_group[bestone].city[i]);
printf("\n");
printf("其他個體如下:\n");
for (int i = 0; i < max_size; i++)
printf("\n"); }}
int main()
tsp問題 遺傳演算法解決
tsp問題最簡單的求解方法是列舉法。它的解是多維的 多區域性極值的 趨於無窮大的複雜解的空間,搜尋空間是n個點的所有排列的集合,大小為 n 1 可以形象地把解空間看成是乙個無窮大的丘陵地帶,各山峰或山谷的高度即是問題的極值。求解tsp,則是在此不能窮盡的丘陵地帶中攀登以達到山頂或谷底的過程。這一篇將...
遺傳演算法解決TSP問題
基本原理在 中有注釋 1 include2 include 3 include 4 include5 include 6 using std string 7 8struct position9 1617 double tsp int n,struct position position,int t...
tsp遺傳演算法
include include include include include include using namespace std define m 10 種群規模 define n 31 省會 首府城市數量 define t 10000 遺傳代數 define earth radius 637...