• 遗传算法解决排序问题


    遗传算法最重要的几个步骤

     1.编码。

      一般可采用二进制编码。本题使用和tsp相同的符号编码(可使用一个数组保存)

     2.选择。根据个体的评分进行选择,涉及到累计概率。

     3.交叉。通过互换基因,从而产生新的个体。

     4.变异。产生新的个体。

      1 #include <stdio.h>
      2 #include <vector>
      3 #include <time.h>
      4 #include <stdlib.h>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 vector<vector<int>> population;
     10 vector<int> best_body;
     11 int min_pair = INT_MAX;//最小的逆序对
     12 
     13 int scale;//种群规模
     14 int arrNum;//基因个数
     15 
     16 int MAX_ROUND;//循环次数
     17 int mutation_times;
     18 
     19 float crossover_p;//交叉概率
     20 float mutation_p;//变异概率
     21 
     22 
     23 //初始化
     24 void init() {
     25     for (int i = 0; i < arrNum; ++i) {
     26         best_body.push_back(0);
     27     }
     28     srand(time(NULL));
     29     for (int i = 0; i < scale; ++i) {
     30         vector<int> temp;
     31         for (int j = 0; j < arrNum;) {
     32             int p = int(((double) rand() / RAND_MAX) * arrNum);
     33             if (find(temp.begin(), temp.end(), p) == temp.end()) {//不存在
     34                 temp.push_back(p);
     35                 ++j;
     36             }
     37         }
     38         population.push_back(temp);
     39     }
     40 
     41 }
     42 
     43 
     44 //逆序对
     45 int reverse_order_pair(vector<int> &vec) {
     46     int sz = vec.size();
     47     int sm = 0;
     48     for (int i = 0; i < sz; ++i) {
     49         for (int j = i + 1; j < sz; ++j) {
     50             if (vec[i] > vec[j]) {
     51                 ++sm;
     52             }
     53         }
     54     }
     55     return sm;
     56 }
     57 
     58 
     59 void copy(vector<int> &v1, vector<int> &v2) {
     60     for (int i = 0; i < arrNum; ++i) {
     61         v1[i] = v2[i];
     62     }
     63 }
     64 
     65 //计算评分 基于逆序对
     66 vector<int> score(vector<vector<int>> &vec) {
     67     vector<int> res;
     68     int temp = INT_MAX;
     69     int index = 0;
     70     for (int i = 0; i < scale; ++i) {
     71         int pairs = reverse_order_pair(vec[i]);
     72         if (pairs < temp) {
     73             temp = pairs;
     74             index = i;
     75         }
     76         res.push_back(pairs);
     77     }
     78 
     79     if (temp < min_pair) {
     80         min_pair = temp;
     81         copy(best_body, vec[index]);
     82     }
     83     return res;
     84 }
     85 
     86 //计算积累概率
     87 vector<double> cumulatePro(vector<int> &score) {
     88     vector<double> res(scale);
     89     double sm = 0;
     90     for (double p:score) {
     91         sm += 1 / (double) p;
     92     }
     93     res[0] = 1 / (double) score[0] / sm;
     94 
     95     for (int i = 1; i < scale; ++i) {
     96         res[i] = 1 / (double) score[i] / sm + res[i - 1];
     97     }
     98     return res;
     99 }
    100 
    101 //选择
    102 vector<vector<int>> choose(vector<double> &cumPro) {
    103     vector<vector<int>> res;
    104     for (int i = 0; i < scale; ++i) {
    105         res.push_back(vector<int>(arrNum));
    106     }
    107     for (int i = 0; i < scale - 1; ++i) {
    108         double temp = (double) rand() / RAND_MAX;
    109 
    110         if (cumPro[0] >= temp) {
    111             copy(res[i], population[0]);
    112         } else {
    113             for (int j = 1; j < scale; ++j) {
    114                 if (cumPro[j - 1] < temp && temp <= cumPro[j]) {
    115                     copy(res[i], population[j]);
    116                     break;
    117                 }
    118             }
    119         }
    120     }
    121     copy(res[scale - 1], best_body);
    122     return res;
    123 }
    124 
    125 
    126 //交叉
    127 //交替位置交叉法
    128 void crossover(vector<int> &v1, vector<int> &v2) {
    129     vector<int> t1;
    130     vector<int> t2;
    131     int i = 0, j = 0;
    132     while (i < v1.size() || j < v2.size()) {
    133         if (find(t1.begin(), t1.end(), v1[i]) == t1.end()) {
    134             t1.push_back(v1[i]);
    135             ++i;
    136         } else if (i < v1.size()) {
    137             t2.push_back(v1[i]);
    138             ++i;
    139         }
    140 
    141         if (find(t1.begin(), t1.end(), v2[j]) == t1.end()) {
    142             t1.push_back(v2[j]);
    143             ++j;
    144         } else if (j < v2.size()) {
    145             t2.push_back(v2[j]);
    146             ++j;
    147         }
    148     }
    149     copy(v1, t1);
    150     copy(v2, t2);
    151 }
    152 
    153 //变异
    154 void mutation(vector<int> &body) {
    155     srand(time(NULL));
    156     for (int i = 0; i < mutation_times; ++i) {
    157         int r1 = (int) ((double) rand() / RAND_MAX * arrNum);
    158         int r2 = (int) ((double) rand() / RAND_MAX * arrNum);
    159         while (r1 == r2) {
    160             r2 = (int) ((double) rand() / RAND_MAX * arrNum);
    161         }
    162         swap(body[r1], body[r2]);
    163     }
    164 }
    165 
    166 
    167 void crossAndMutation(vector<vector<int>> &newPop) {
    168     srand(time(NULL));
    169     for (int i = 0; i < scale - 1; i += 2) {
    170         float p1 = (float) rand() / RAND_MAX;
    171         if (p1 > crossover_p) {//交叉
    172             crossover(newPop[i], newPop[i + 1]);
    173         }
    174     }
    175     //变异
    176     for (int i = 0; i < scale; ++i) {
    177         float p1 = (float) rand() / RAND_MAX;
    178         if (p1 > mutation_p) {
    179             mutation(newPop[i]);
    180         }
    181     }
    182 }
    183 
    184 //修正 将上一代最优的替换新一代最差的
    185 void fixUp(vector<vector<int>> &newPop) {
    186     int index = 0;
    187     int pairs = 0;
    188     for (int i = 0; i < scale; ++i) {
    189         if (reverse_order_pair(newPop[i]) > pairs) {
    190             pairs = reverse_order_pair(newPop[i]);
    191             index = i;
    192         }
    193     }
    194     copy(newPop[index], best_body);
    195 }
    196 
    197 
    198 int main() {
    199     scale = 50;//种群规模
    200     arrNum = 7;//基因个数
    201     MAX_ROUND = 100;//循环次数
    202     mutation_times = 4;//变异次数
    203     crossover_p = 0.6;//交叉概率
    204     mutation_p = 0.4;//变异概率
    205     init();
    206     for (int i = 0; i < MAX_ROUND; ++i) {
    207         vector<int> scoreVec = score(population);//评分
    208         vector<double> pArr = cumulatePro(scoreVec);//积累概率
    209         vector<vector<int>> newPop = choose(pArr);//选择
    210         crossAndMutation(newPop);//交叉和变异
    211         fixUp(newPop);//修正
    212         population = newPop;
    213     }
    214     for (int temp:best_body) {
    215         printf("%d ", temp);
    216     }
    217     return 0;
    218 }

    最开始没有精英策略,算法很不稳定,加入精英策略之后,算法变得比较稳定。

    实例代码执行结果:

    0 1 2 3 4 5 6

  • 相关阅读:
    Java异常的深层次理解
    Java笔记1_java基础
    oracle怎么实现id自增和设置主键
    C51最小系统
    文本输入方式的pspice仿真步骤
    外部中断实验
    客户端测试
    定时器实验
    linklist template
    dfs:10元素取5个元素的组合数
  • 原文地址:https://www.cnblogs.com/oldBook/p/9866734.html
Copyright © 2020-2023  润新知