算法理解-遗传算法(Genetic Algorithm)(一个带计算过程的例子)

article/2025/11/6 21:36:19

想要快速的了解一个算法,最好的方式便是拿个例子手动进行实现算一遍。这里借鉴了网络上的一个例子,求解如下的一个函数:

f(x)=xsin(10πx)+2x[1,2]

其函数图像为:
suitFun
例子来源:
http://blog.csdn.net/emiyasstar__/article/details/6938608/

求解流程与概念

染色体(编码)

在遗传算法中,一个个体一般只包含一条染色体。染色体上包含这一组基因组。

  • 基因 ( Gene ) :一个遗传因子。
  • 染色体 ( Chromosome ) :一组的基因。
  • 个体 ( individual ):单个生物。
  • 群体:一群个体

在上述的例子中自变量只有x,所有只有一个gene,因此在本例子中:

==

将x表达为gene的过程,称之为编码,常见的编码格式有二进制编码和浮点编码。本文采用2进制编码:

  • 设我们求解精度为 e=0.01
  • 那么我们需要将x的区间【-1,2】,切分成 (21)/0.01=300 份。
  • 又因为采用二进制编码所以实际需要的编码位数为: 28=256<300<29=512 故当我们需要精度为0.01时,采用二进制编码最少需要9位数。
  • 那么实际的求解精度为:
    e=35120.00586

有编码就存在着解码,按照本文的例子,可以想到以下的映射:

000000000=1111111111=2

因此可以得到以下的解码公式:
(111111111)into10e1=51235121=2(000000000)into10e1=01=1

ps:忽略上述由二进制转换为十进制的写法细节,不知道怎么写其数学表达式。
其中编码和解码的R代码

GetCodeParameter <- function(e, limitX){# 获取编码的缩放比例,用于解码或者编码(二进制)# Args : e:求解精度#        limitX:X的范围# return: bitsPower:二进制编码位数#         e:真实求解精度#         diff:解码公式的中的常数range <- limitX[2] - limitX[1] # 区间长度splitNum <- range/e            # 需要切割位数bitsPower <- 1 while(2^bitsPower <= splitNum ){bitsPower <- bitsPower + 1}xMax <- max(limitX)e <- range/2^bitsPower        # 精度大小diff <- 2^bitsPower*e - xMax  # 缩放差值 1 c(bitsPower, e, diff)         # 返还结果 
}DeCode <- function(x, limitX, codeParameter){# 解码# Args: x:需要解码的个体#       limitX: x的取值范围#       codeParameter:包含bitsPower、e、diff# return:x:解码后的xx <- strtoi(x, base = 2) # 转换为10进制x <- x*codeParameter[2]-codeParameter[3]x
}

适者生存

适者生存 ( The survival of the fittest ):对环境适应度高的个体参与繁殖的机会比较多,后代就会越来越多。适应度低的个体参与繁殖的机会比较少,后代就会越来越少。
适应度指的是求解的目标,该例子中适应度计算公式便是求解的目标:

f(x)=xsin(10πx)+2

其中 f(x) 便是适应度计算公式。
适者生存其实指的是对后代的一种选择策略,常见的选择策略有轮盘赌、锦标赛、精英保留策略。轮盘赌就是按照一定的概率抽取子代,重复n次,每个个体被抽中的概率为:
pi=f(xi)nj=1f(xj)

轮盘赌举例说明:

# 有这么一个由10个个体组成的群体
group <- CreateGroup(groupNum, codeParameter)
group
# "101100100" "010001100" "000010010" "010010011" "000011101" 
# "011001111" "000001100" "000011010" "111100000" "000001011"# 计算每人的适应度
adaptive <- myFun(group)  # myFun = x*sin(10pi*x)+2
# 2.464  1.893  2.153  1.870  2.673 
# 2.084  1.253  2.845  2.694  1.159  # 每人的生存概率
existProb <- adaptive/sum(adaptive)
# 0.117 0.090 0.102 0.089 0.127 
# 0.099 0.059 0.135 0.128 0.055# 按照生存概率生成下一代,即重复放回抽取N次。
group <- sample(group, groupNum,prob = existProb, replace = T)
group # 新的群体
# "000001100" "000010010" "101100100" "010010011" "010001100" 
# "000011010" "000010010" "011001111" "000011010" "000001011"# 产生的下一代中有一些人被淘汰了
length(unique(group))
8

锦标赛进行优胜劣汰的方法是:每次从群体中随机抽取p个人,将p个人中适应度最好的保留下来,重复N次,得到N个保留下的个体形成下一代。

交叉

交叉指的是交换染色体片段产生后代两个新的后代,例如典型的单点交叉方式:随机选择两个个体进行交叉,按照以下的方式产生新的子代。
基因交换
配上代码

candidate  <- 1:groupNum       # 可以进行配对的下标
parentNum <- floor(groupNum/2) # 父母对,这里10个群体有5对# 随机配成5对
parentInx1 <- sample(candidate, parentNum, replace = F)                              
parentInx2 <- sample(candidate[!candidate %in% parentInx1], parentNum, replace = F) 
parentInx1  
# 3   5  8  9  6
parentInx2
# 10  4  1  7  2# 这里便形成了5对, 3与10配对, 5与4配对···
# 以其中一对举例,"101100100" "000001011"
# 随机产生交换点,codeParameter[1] = 9为编码的长度
matingPoint <- sample(2:(codeParameter[1]-1), 1, replace = T) 
matingPoint
# 6
previousGene_1 <- substr(parent1, 1, matingPoint[i2]) # 提取前半段
lastGene_1 <- substr(parent1, matingPoint[i2]+1, codeParameter[1]) # 提取后半段
previousGene_2 <- substr(parent2, 1, matingPoint[i2])
lastGene_2 <- substr(parent2, matingPoint[i2]+1, codeParameter[1])
# 交叉,产生后代
child_1 <- paste(previousGene_1, lastGene_2, sep="")
child_2 <- paste(previousGene_2, lastGene_1, sep="")
child_1;child_2 
#"101100011" "000001100"

交叉操作存在着多种方式,例如:多点杂交、均匀杂交,离散杂交、中间杂交、线性杂交和扩展线性杂交等算法。其中有些交叉操作是基于编码的方式的。

变异

变异的作用,指的是染色体的某个基因片段或者某个基因点发生突变。例如单点突变可以通过下图进行表示:
这里写图片描述
突变的作用,是希望能够摆脱局部最优点,往更好的地方去。但是效果具有很大的随机性。

mutationProb <- 0.01 # 变异概率
# 按照突变概率生成10个0和1,1表示发生突变,0表示没有发生突变
mutationGene <- sample(c(0,1), groupNum, replace = T,prob = c(1-mutationProb, mutationProb))
mutationGene
# 0 0 0 0 0 1 0 0 0 0# 变异位置下标
mutationIdx <- which(mutationGene==1)
lenMutation <- length(mutationIdx)
if (lenMutation> 0) { # 当存在变异的基因时# 根据变异个数,随机k个产生变异位置matingPoint <- sample(1:codeParameter[1], lenMutation, replace = T) for (i in 1:lenMutation){# 变异group[mutationIdx[i]] <- Mutation(group[mutationIdx[i]], matingPoint[i]) }}

总流程

遗传算法的求解过程,是一个不断重复的过程,其流程如图所示:
流程图

求解结果

贴图比较好展示:
结果

这里附上一个小知识:
假如在R中想要将其过程以一个动态过程展示出来,可以通过animation包进行实现。其中HTML格式输出的话,还能进行交互式的调整展示的速度。
其过程也很简单,每次迭代时,都将图画扔进一个list当中然后print出来。例如:

library(animation)
saveHTML({for(i in 1:93){print(plotGA[[i]])}
})

效果如下:
这里写图片描述

代码汇总

#1. 初始化
#--- 目标函数
myFun <- function(x){   # 求解函数 亦 适应度函数x*sin(10*pi * x) + 2
}
#--- 求解参数
limitX <- c(-1, 2)   # 【-1,2】之间取值
e <- 0.01            # 小数点后2位 
groupNum <- 50       # 产生的群体数
mutationProb <- 0.01 # 变异概率
generation <- 500    # 迭代数目
plotGA <- list()     # 存储图片,画连续图用#2. 编码
#--- 获取编码参数
codeParameter <- GetCodeParameter(e, limitX)
#--- 产生群体
group <- CreateGroup(groupNum, codeParameter)#3. 种群繁衍过程
for(i in 1:generation){#3.1 计算适应度deCodeGroup <-  DeCode(group, limitX, codeParameter) adaptive <- myFun(deCodeGroup)          #3.2 适者生存existProb <- adaptive/sum(adaptive)# 计算生存概率group <- sample(group, groupNum,prob = existProb, replace = T) # 生存的个体#--- plotmeanAdaptive <- mean(adaptive)maxAdaptive <- max(adaptive)main <- paste("generation", i)plotGA[[i]] <- plotShow(x = deCodeGroup, y = adaptive, limitX, main, meanAdaptive, maxAdaptive)#3.3 杂交(两两配对)#--- 选择配对对象candidate  <- 1:groupNumparentNum <- floor(groupNum/2)parentInx1 <- sample(candidate, parentNum, replace = F)                              #parentInx2 <- sample(candidate[!candidate %in% parentInx1], parentNum, replace = F)  ##--- 选择配对点matingPoint <- sample(2:(codeParameter[1]-1), parentNum, replace = T)#--- 配对newgroup <- NULLfor(i2 in 1:parentNum){previousGene_1 <- substr(group[parentInx1[i2]], 1, matingPoint[i2])lastGene_1 <- substr(group[parentInx1[i2]], matingPoint[i2]+1, codeParameter[1])previousGene_2 <- substr(group[parentInx2[i2]], 1, matingPoint[i2])lastGene_2 <- substr(group[parentInx2[i2]], matingPoint[i2]+1,codeParameter[1])child_1 <- paste(previousGene_1, lastGene_2, sep="")child_2 <- paste(previousGene_2, lastGene_1, sep="")newgroup <- c(newgroup, child_1, child_2)}single <- which(!candidate %in% c(parentInx1, parentInx2))  # 将单身狗添加回去group <- c(newgroup, group[single])#3.4 变异#--- 选择变异基因mutationGene <- sample(c(0,1), groupNum, prob = c(1-mutationProb, mutationProb), replace = T)#--- 变异位置点mutationIdx <- which(mutationGene==1)#--- 变异(0 -> 1; 1 -> 0)lenMutation <- length(mutationIdx)if( lenMutation> 0){matingPoint <- sample(1:codeParameter[1], lenMutation, replace = F)for (i in 1:lenMutation){group[mutationIdx[i]] <- Mutation(group[mutationIdx[i]], matingPoint[i])}}#3.5 结束条件if((maxAdaptive - meanAdaptive) <= e) break()
}

其他求解方法

粒子群:
http://blog.csdn.net/qq_27755195/article/details/62216762
模拟退火:
http://blog.csdn.net/qq_27755195/article/details/62505046


http://chatgpt.dhexx.cn/article/jZKLvJcy.shtml

相关文章

遗传算法及python实现

目录 一、遗传算法概念 二、遗传算法应用实例 基础概念&#xff1a; 1、种群和个体&#xff1a; 2、编码、解码与染色体&#xff1a; 3、适应度和选择&#xff1a; 4、 交叉、变异&#xff1a; 三、遗传算法python完整代码 “适者生存&#xff0c;不适者淘汰” …

遗传算法详解python代码实现以及实例分析

遗传算法 文章目录 遗传算法前言一、遗传算法是什么&#xff1f;二、实例讲解例题11.初始化种群2.优胜劣汰3.根据优胜劣汰的结果&#xff0c;交配生殖、变异5.生物遗传进化 例题21.初始化参数2.定义环境&#xff08;定义目标函数&#xff09;3.DNA解码&#xff08;计算x&#x…

遗传算法实例解析

遗传算法实例及MATLAB程序解析 遗传算法Genetic Algorithms&#xff0c;GA&#xff09;是一种基于自然选择原理和自然遗传机制的搜索&#xff08;寻优&#xff09;算法&#xff0c;它是模拟自然界中的生命进化机制&#xff0c;在人工系统中实现特定目标的优化。遗传算法的实质是…

遗传算法详解及代码实现

遗传算法 定义相关术语交叉变异产生子代完整过程 遗传算法应用问题的提出与解决方案“袋鼠跳”问题爬山法&#xff08;最速上升爬山法&#xff09;模拟退火遗传算法 遗传算法实现过程遗传算法的一般步骤遗传算法图解进化细节种群和个体编码方法二进制编码浮点编码法符号编码法 …

遗传算法详解

转载&#xff1a;https://blog.csdn.net/u010451580/article/details/51178225 三&#xff1a;遗传算法 照例先给出科学定义&#xff1a; 遗传算法&#xff08;Genetic Algorithm, GA&#xff09;起源于对生物系统所进行的计算机模拟研究。它是模仿自然界生物进化机制发展起…

遗传算法(Genetic Algorithm)详解与实现

遗传算法&#xff08;Genetic Algorithm&#xff09;详解与实现 遗传算法简介类比达尔文进化论达尔文进化理论遗传算法对应概念 遗传算法理论图式定理&#xff08;schema theorem&#xff09; 遗传算法与传统算法的差异遗传算法的优缺点优点局限性 遗传算法应用场景遗传算法的组…

经典遗传算法及MATLAB实例

经典遗传算法及简单实例&#xff08;MATLAB&#xff09; 1. 遗传算法简单介绍1.1 理论基础1.2 算法要点1.1 编码1.2 适应度函数 1.3 基本流程 2. 代码实例&#xff08;MATLAB&#xff09;2.1 代码汇总2.1 初始化种群2.2 计算适应度2.3 迭代终止判断2.4 自然选择&#xff08;轮盘…

遗传算法及实例

遗传算法是模拟生物在自然环境下遗传的过程而形成的自适应全局优化搜索算法。如果把某个问题的可行域看作是一个族群&#xff0c;目标函数看作是自然选择的条件&#xff0c;那么&#xff0c;这个族群通过一代又一代的繁衍和进化最终变成最接近筛选条件的样子。遗传算法就是利用…

遗传算法原理及算法实例

遗传算法原理解析 遗传算法&#xff08;GA&#xff09;是一种元启发式自然选择的过程&#xff0c;属于进化算法&#xff08;EA&#xff09;大类。遗传算法通常是利用生物启发算子&#xff0c;如变异、交叉和选择来生成高质量的优化和搜索问题的解决方案。 借鉴生物进化理论&…

遗传算法小结及算法实例(附Matlab代码)

目录 1、遗传算法流程 2、关键参数说明 &#xff08;1&#xff09;群体规模 \(NP\) &#xff08;2&#xff09;交叉概率 \(P_c\) &#xff08;3&#xff09;变异概率 \(P_m\) &#xff08;4&#xff09;进化代数 \(G\) 3、MATLAB仿真实例 3.1 遗传算法求解一元函数的极…

遗传算法(Genetic Algorithm,GA)实例详解

遗传算法是模拟生物在自然环境中的遗传和进化的过程而形成的自适应全局优化搜索算法&#xff0c;他能有效求解NP问题以及非线性、多峰函数优化和多目标优化问题。 1.理论基础 1.1生物学基础 遗传算法的生物学基础是借鉴了达尔文的进化论和孟德尔的遗传学说&#xff0c;一个种…

遗传算法设计实例

1.遗传算法实例程序设计 随机初始化种群P(t){x1,x2…xn),计算P(t)中个体的适应值。其MATLAB程序的基本格式如下: Begin t0 初始化P(t) 计算P(t)的适应值; while (不满足停止准则)dobegintt1从P(t1)中选择P(t)重组P(t)计算P(t)的适应值 end例1 求函数 f(x) 9*sin(5x) cos(4x)…

遗传算法GA原理详解及实例应用 附Python代码

遗传算法GA 遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型&#xff0c;是一种通过模拟自然进化过程搜索最优解的方法。 生物在自然界中的生存繁衍&#xff0c;显示了其对自然环境的优异的自适…

vue实现点击下载exe,运行报错shellexecuteex失败 代码2

页面效果 exe插件放在vue项目的public文件夹里&#xff0c;然后用a标签实现点击下载 <a href"/VideoWebPlugin.exe">下载插件</a> 成功下载后运行报错 解决方法&#xff1a;选择在文件夹中显示&#xff0c;右击属性&#xff0c;在兼容性设置里的以管理员…

VC++分别使用WinExec、CreateProcess、ShellExecute和ShellExecuteEx来启动程序(附源码)

VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)

API函数ShellExecute与ShellExecuteEx用法

ShellExecute: 1.函数功能:你可以给它任何文件的名字,它都能识别出来并打开它。2.函数原型: HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd ); 3.参数说明:hwnd:用于指定父窗口句…

C/C++ 使用 API 函数 ShellExecuteEx 实现文件打印

本文章主要介绍使用ShellExecuteEx实现打印文件的功能。 函数原型&#xff1a;BOOL ShellExecuteExA(__inout SHELLEXECUTEINFOA *pExecInfo) 输入输出参数都是 SHELLEXECUTEINFO 结构体。 SHELLEXECUTEINFO定义&#xff1a; typedef struct _SHELLEXECUTEINFO { DWORD c…

Windows函数 ShellExecuteEx

点击进入视频教程 代码&#xff1a; #include<windows.h> #include<tchar.h> #pragma comment(lib, "Urlmon.lib") int WINAPI _tWinMain(HINSTANCE hinstance, HINSTANCE hPreInstance, LPTSTR lpCmdLine, int nShowCmd) {// 下载图片&#xff0c;并保…

UpdatePanel终于可以上传文件了!

我们要做的&#xff0c;只是在页面上添加一个控件而已。 不过&#xff0c;其实这只是个半成品&#xff0c;或者说是一个原型&#xff0c;但是很明显&#xff0c;我们做对了。:) 在实现上&#xff0c;我曾经在两个做法上斟酌了许久&#xff0c;第一种是继承ScriptManager&#x…

updatepanel 排版问题

使用 ASP.NET AJAX 開發人員&#xff0c;一定不會錯過 UpdatePanel 這個超級控制項&#xff0c;它可以讓輕易的讓原有設計的頁面很輕易的具有 AJAX 的效果。可是在設計階段使用 UpdatePanel 去排版常造成我們的困擾&#xff0c;放置在 UpdatePanel 中的控制項無法正確呈現實際的…