zoukankan      html  css  js  c++  java
  • 缩水版遗传算法 学习笔记

    遗传算法是在随机的初始数据下,经过一段时间的变化,最后收敛得到针对某类特定问题的一个或者多个解。

    主要步骤有编码 选择 交叉 变异

    这里以一个极其简单的探索迷宫出路的代码为例 增加对遗传算法的感性认识。

    编码
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,8,1,0,0,0,0,0,0,0,1,0,0,1,1,
    1,0,1,0,1,0,1,1,1,0,0,0,0,0,1,
    1,0,1,0,1,0,1,1,1,1,0,1,0,1,1,
    1,0,0,0,1,0,0,0,0,0,0,1,0,5,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

    我们定义这样一个迷宫
    1表示为不可到达地点
    0表示可通过区域
    5是起点 8是终点
    我们再定义一系列行走出迷宫的行走方向数组 walk[TestStep](walk[50]).这个数组记录了走50步的方向
    方向使用0-3来代替 0 表示向上走,1表示向下走,2表示向左走,3表示向右走。然后测试这一系列走法在迷宫能达到的坐标,以达到的位置和终点的XY的差值的倒数作为这个走法的评分
    price = 1/(1.0+(abs(exitIndex.x-vMethods[i].currentPosIndex.x)+abs(exitIndex.y-vMethods[i].currentPosIndex.y)));

    考虑到XY的差值可能为零,所以额外加了一个1.0;以上就是编码的步骤;


    选择

    作为进化演变下一代的元素,我们需要选择评分比较高的走法

    通常的办法是轮盘赌选择 根据评分的高低 决定其被选中的几率

     

    各个个体被选中的概率与其适应度函数值大小成正比。设群体大小为n ,个体i 的适应度为 Fi,则个体i 被选中遗传到下一代群体的概率为:

    比如说

    走法A 评分0.5

    走法B 评分0.2

    走法C 评分0.3

    那么根据一个随机范围为0-99的随机数

    如果数目在0-49之间 则选择走法A

    如果数目在50-69之间则选择走法B

    如果数目在70-99之间则选择走法C

    我的代码中 写的比较简单 直接选择评分在前一半的作为进化演变的元素

    int index1 = rand()%(TrySize/2);

    int index2 = rand()%(TrySize/2);

    缺点是可能逐步演化中 族群的走法都慢慢接近 甚至编程一样 从未导致没有变化 得不到正确结果

    优点是 代码简单

    交叉

    2个元素交换部分结构,来构造下一代新的元素

    例如

    走法A 01230123 0123

    走法B 12301230 1230

    构造下一代走法

    01230123 1230

    代码中为

    Method m = CrossOver(vMethods[index1],vMethods[index2]);

    突变

    对元素数据进行小概率的调整 以调整进化的集中性 避免所有元素同一化

    代码中是以25%的概率 对某一步的走法进行调整

    if((rand()%100)>75)

    {

    int index = rand()%TestStep;

     m.walk[index] = direction(rand()%4);

    }

    本节代码属于实验性代码 对具体参数和一些算法都做了简化 只是加深对算法的理解 方便入门

    至于算法的选择 参数优化调整的理论依据 均未涉及 需要学习理论教程书籍

    代码如下

      1 #include <iostream>
      2 #include <ctime>
      3 #include <cstdlib>
      4 #include <vector>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 int mapArray[6][15] = { 2,3,4,1,1,1,1,1,1,1,1,1,1,1,1,
     10                         1,8,1,0,0,0,0,0,0,0,1,0,0,1,1,
     11                         1,0,1,0,1,0,1,1,1,0,0,0,0,0,1,
     12                         1,0,1,0,1,0,1,1,1,1,0,1,0,1,1,
     13                         1,0,0,0,1,0,0,0,0,0,0,1,0,5,1,
     14                         1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
     15 struct Point{
     16     int x;
     17     int y;
     18 };
     19 
     20 Point startIndex = {4,13};
     21 Point exitIndex = {1,1};
     22 
     23 enum direction{
     24     Mup =0,
     25     Mdown ,
     26     Mleft ,
     27     Mright };
     28 
     29 #define TestStep    50
     30 #define TrySize     50
     31 
     32 
     33 struct Method{
     34     direction walk[TestStep];
     35     Point   currentPosIndex;
     36     double price;
     37 };
     38 
     39 vector<Method> vMethods;
     40 vector<Method> vNewMethods;
     41 
     42 
     43 bool SortByPrice(const Method& obj1,const Method& obj2)
     44 {
     45     return obj1.price>obj2.price;
     46 }
     47 
     48 void InitRandomWalk(direction walk[]){
     49     for(int i = 0;i< TestStep;++i){
     50         walk[i] = direction(rand()%4);
     51     }
     52 }
     53 
     54 bool Walk(Point& currentPosIndex,direction walk[],int length){
     55     for(int i = 0;i< TestStep;++i){
     56         if(walk[i] == Mup){
     57             if( (currentPosIndex.x-1)>=0 &&
     58                mapArray[currentPosIndex.x-1][currentPosIndex.y] != 1){
     59                 currentPosIndex.x -= 1;
     60             }
     61         }else if(walk[i] == Mdown){
     62             if( (currentPosIndex.x+1)<=5 &&
     63                mapArray[currentPosIndex.x+1][currentPosIndex.y] != 1){
     64                 currentPosIndex.x += 1;
     65             }
     66         }else if(walk[i] == Mleft){
     67             if( (currentPosIndex.y-1)>=0 &&
     68                mapArray[currentPosIndex.x][currentPosIndex.y-1] != 1){
     69                 currentPosIndex.y -= 1;
     70             }
     71         }else if(walk[i] == Mright){
     72             if( (currentPosIndex.y+1)<=14 &&
     73                mapArray[currentPosIndex.x][currentPosIndex.y+1] != 1){
     74                 currentPosIndex.y += 1;
     75             }
     76         }
     77         if(currentPosIndex.x == exitIndex.x && currentPosIndex.y == exitIndex.y){
     78             return true;
     79         }
     80     }
     81 
     82     return false;
     83 }
     84 
     85 Method CrossOver(const Method& m1,const Method& m2){
     86     int i = rand()%TestStep;
     87     Method m;
     88 
     89     for(int j = 0; j <= i ;++j){
     90         m.walk[j] = m1.walk[j];
     91     }
     92 
     93     for(int k =i;k < TestStep;++k){
     94         m.walk[k] = m2.walk[k];
     95     }
     96     return m;
     97 }
     98 
     99 bool run(){
    100 
    101     for(int i = 0;i < TrySize;++i){
    102        vMethods[i].currentPosIndex.x = startIndex.x;
    103        vMethods[i].currentPosIndex.y = startIndex.y;
    104        if(Walk(vMethods[i].currentPosIndex, vMethods[i].walk,TestStep)){
    105            cout << "walk to exit!!!" << endl;
    106            return true;
    107        }
    108        vMethods[i].price = 1/(1.0+(abs(exitIndex.x-vMethods[i].currentPosIndex.x)+abs(exitIndex.y-vMethods[i].currentPosIndex.y)));
    109        cout << "current pos:	" << vMethods[i].currentPosIndex.x <<" " << vMethods[i].currentPosIndex.y <<"	price:"<< vMethods[i].price<< endl;
    110     }
    111 
    112     sort(vMethods.begin(),vMethods.end(),SortByPrice);
    113     for(int i = 0 ; i <TrySize;i++){
    114         int index1 = rand()%(TrySize/2);
    115         int index2 = rand()%(TrySize/2);
    116 
    117 //        for(int k = 0 ;k<TestStep;++k){
    118 //            cout << vMethods[index1].walk[k];
    119 //        }
    120 //        cout << endl;
    121 
    122       Method m = CrossOver(vMethods[index1],vMethods[index2]);
    123        if((rand()%100)>75)
    124        {
    125            int index = rand()%TestStep;
    126            m.walk[index] = direction(rand()%4);
    127 
    128        }
    129        vNewMethods.push_back(m);
    130 //        for(int k = 0 ;k<TestStep;++k){
    131 //            cout << vMethods[index1].walk[k];
    132 //        }
    133 //        cout << endl;
    134     }
    135     vMethods = vNewMethods;
    136     vNewMethods.clear();
    137     return false;
    138 }
    139 
    140 
    141 
    142 
    143 
    144 int main(int argc, char *argv[])
    145 {
    146     vMethods.clear();
    147     srand( (unsigned)time( NULL ) );
    148     for(int i = 0;i < TrySize;++i){
    149         Method m;
    150         InitRandomWalk( m.walk);
    151         vMethods.push_back(m);
    152     }
    153 
    154     int64_t count = 0;
    155     while(!run()){
    156         count++;
    157     }
    158     cout << "run " << count << " times." << endl;
    159 
    160 
    161     return 0;
    162 }
    View Code

     截图来自 《游戏编程中的人工智能》

    代码为该书本代码中的缩水精简版


    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Nginx支持WebSocket反向代理-学习小结
    CentOS6.9下升级默认的OpenSSH操作记录(升级到OpenSSH_7.6p1)
    CentOS 6下gcc升级的操作记录(由默认的4.4.7升级到6.4.0版本)
    Docker容器内部端口映射到外部宿主机端口
    Linux下分布式系统以及CAP理论分析
    C/ C++ 快速上手
    YUV视频格式详解(翻译自微软文档)
    YUV详解
    阿里云ECS使用vnc远程连接(Ubuntu + CentOS)
    oh-my-zsh: 让终端飞
  • 原文地址:https://www.cnblogs.com/itdef/p/6806997.html
Copyright © 2011-2022 走看看