遗传算法入门(连载之六)

2024-06-10 14:08

本文主要是介绍遗传算法入门(连载之六),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   最近在学习有关遗传算法和神经网络方面的知识,网上查看了很多这方面的秘笈,只怪小生天生愚钝、才疏学浅,不能很好的领悟秘笈中的真谛,往往被弄得晕头转向、不知所措快哭了委屈。直到有一天无意中看到了博主zzwu写的有关这方面的文章,初读之,如温旧习;渐深入,觉甚好;遂一气呵成,犹如拨云见日、茅塞顿开。余甚怕在茫茫Internet中再无机会拜读之,遂收藏于此,以便众人观之,绝无其他不良用途。在此对博主再次深表感谢。

博文转自:http://blog.csdn.net/zzwu/article/details/561625



.
(连载之六)
.
扎自<游戏编程中的人工智能技术>第三章

 清华大学出版社

(本章由zzwu译)

 

3.4.1为染色体编码
(Ecoding the Chromosome)

           每个染色体必须把小人Bob 的每一个行动编入代码中。Bob的行动仅限为4个方向向东(East),向南(South),向西(West),向北(North)故编码后的染色体应该就是代表这4个方向信息的一个字符串。传统的编码方法就是把方
向变换成二进制的代码。四个方向只要2位就够了,例如下表所示的那样: 
二进制代码十进制译码代表的方向
000向北
011向南
102向东
113向西

 这样,如果你得到了一个随机的二进制字符串,你就能将它译码出Bob行动时所遵循的

一系列方向。例如染色体:
111110011011101110010101

代表的基因就是          11,11,10,01,10,11,10,11,10,01,01,01当把二进制代码译成十进制时,就成为
            3,3,2,1,2,3,2,3,2,1,1,1再把这些放进一个表格中,就可以使你相信这是一样的一些概念: 
        
二进制代码十进制译码代表的方向
113West
113West
102East
011South
102East
113West
102East
113West
102East
011South
011South
011South

      到此,你要做的全部就是将Bob置于迷宫的起点,然后告诉他根据这张表所列的方向一步步地走。如果按某一个方向前进将使Bob碰到墙壁或障碍物,则只需忽略该方向并继续按下一个方向去走就行了。这样不断下去,直到所有方向用光或Bob到达出口时为止。
    
    如果你想象有几百个这样的随机的染色体,你就能看到它们中的某些可能为Bob译码出到达出口的一套方向(问题的一个解),但它们中的大多数将是失败的。
    
    遗传算法以随机的2进制串(染色体)作为初始群体,测试它们每一个能让Bob走到离开出口有多么接近,然后让其中最好的那些来孵化后代,期望它们的子孙中能有比Bob走得离出口更近一点。这样继续下去,直到找出一个解,或直到Bob绝望地在一个角落里被粘住不动为止(你将看到,这种情况是可能发生的)。
      
    因此,我们应定义一种结构,其中包含一个2进制位串(染色体),以及一个与该染色体相联系的适应性分数。我把这个结构称为SGenome结构,它的定义如下:  
  

struct SGenome    {      vector <int>  vecBits;      double   dFitness;      SGenome():dFitness(0){}      SGenome(const int num_bits):dFitness(0)      {        //创造随机二进制位串        for (int i=0; i<num_bits; ++i)          {             vecBits.push_back(RandInt(0,1));          }      }   };     
正如你能见到的那样,如果你在创建SGenome对象时把一个整型数作为参数传递给构造函数,则它就会自动创建一个以此整数为长度的随机2进制位串,
并将其适应性分数初始化为零,这样就把基因组什么都准备好了。
  
程序注释std::vectorSTL(Standard Templete Library)标准模板库的一部分, 这是一种为处理动态数组而预先建立好的类。如果要把数据加入STL中,可使用
push_back()方法。

下面是一个简单的例子:
  
  #include <vector>   for (int i=0; i<10; i++)     {         MyFirstVector.push_back(i);             cout << endl << MyFirstVector[i];     }
要清空一个向量,使用clear()方法
        MyFirstVector.clear();

你可利用size()方法来得到向量中元素的数目
NyFirstVector.size()

就是这样。
  不需要你去考虑内存管理问题-std::vector能够为你来做所有这些!当需要时,我会在整个程序中使用它。
SGenome结构中不具备怎样为染色体(vecBits)进行译码的知识; 这是需要由遗传算法类自己来完成的一项任务。现在让我们来快速窥视一下这个类的定义。
我已把它称作CgaBob类(有时我对我的原始创见自己也很吃惊,但我确实是这样做的)。
  
class CgaBob
{
private:
//基因组群体
vector<SGenome> m_vecGenomes
//群体的大小
int m_iPopSize
double m_dCrossoverRate;
double m_dMutationRate;
//每个染色体含有多少bits
int m_iChromoLength;
//每个基因有多少bits
int m_iGeneLength;
int m_iFittestGenome;
double m_dBestFitnessScore;
double m_dTotalFitnessScore;
int m_iGeneration;
//为 map 类创建一个实例
CBobsMap m_BobsMap;
//另一个CbobsMap对象用来保存每一代的最佳路径的一个记
//录,这是被访问小格的一个数组,它仅仅是为了显示目的而使用的。
CBobsMap m_BobsBrain;
//让你知道运行是否仍在进行中
bool m_bBusy;
void Mutate(vector<int>&vecBits);
void Crossover(const vector<int>&mum,  
               const vector<int>&dad,  
               vector<int>&baby1,
               vector<int>&baby2);
SGenome& RouletteWheel Selection();
//用新的适应性分数来更新基因组原有的适
//应性分数,并计算群体的最高适应性分数和适应性分数最高的那个成员。
void UpdateFitnessScores();
//把一个位向量译成为一个方向的(整数)向量
vector<int> Decode(const vector<int> &bits);
//把一个位向量变换为十进制数。用于译码
int BinToInt(const vector<int> &v);
//创建一个随机的二进制位串的初始群体
void CreateStartPopulation();
public:
CgaBob(double cross_rat,
        double mut_rat,
       int pop_size,
       int num_bits,
      int gene_len):m_dCrossoverRate(cross_rat),
                      m_dMutationRate(mut_rat),
                      m_iPopSize(pop_size),
                      m_iChromoLength(num_bits),
                      m_dTotalFitnessScore(0.0),
                      m_iGeneration(0),
                      m_iGeneLength(gene_len),
                      m_bBusy(false)
{
  CreateStartPopulation();
}
void Run(HNND hwnd);
void Epoch();
void Render(int cxClient, int cyClient, HDC surface);
//访问用的方法
int Generation(){return m_iGeneration;}
int GetFittest(){return m_iFittestGenome;}
bool Started(){return m_bBusy;}
void Stop(){m_bBusy = false;}
};

由上你可看出,当这个类的一个实例被创建时,构造函数初始化所有的变量,并调用CreateStartPopulation()。这一短小函数创建了所需数量的基因组群体。

每个基因组一开始包含的是一个由随机2进制位串组成的染色体,其适应性分数则被设置为零。


-连载6完-

这篇关于遗传算法入门(连载之六)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048376

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

C语言指针入门 《C语言非常道》

C语言指针入门 《C语言非常道》 作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。 但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是: 李忠老师官网 最棒的是,有配套的教学视频,可以试看。 试看点这里 接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非

MySQL入门到精通

一、创建数据库 CREATE DATABASE 数据库名称; 如果数据库存在,则会提示报错。 二、选择数据库 USE 数据库名称; 三、创建数据表 CREATE TABLE 数据表名称; 四、MySQL数据类型 MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串类型 4.1 数值类型 数值类型 类型大小用途INT4Bytes整数值FLOAT4By

【QT】基础入门学习

文章目录 浅析Qt应用程序的主函数使用qDebug()函数常用快捷键Qt 编码风格信号槽连接模型实现方案 信号和槽的工作机制Qt对象树机制 浅析Qt应用程序的主函数 #include "mywindow.h"#include <QApplication>// 程序的入口int main(int argc, char *argv[]){// argc是命令行参数个数,argv是