遗传算法原理及算法实例

article/2025/11/6 22:41:34

遗传算法原理解析

遗传算法(GA)是一种元启发式自然选择的过程,属于进化算法(EA)大类。遗传算法通常是利用生物启发算子,如变异、交叉和选择来生成高质量的优化和搜索问题的解决方案。

借鉴生物进化理论,遗传算法将问题模拟成一个生物进化过程,通过遗传、交叉、突变、自然选择等操作产生下一代的解,并逐步淘汰适应度函数值低的解,增加适应度函数高的解。这样进化N代后就很有可能会进化出适应度函数值很高的个体。

与遗传算法有关的生物学概念:

(1)染色体(chromosome)
生物是由细胞组成,每一个细胞中都有一套相同的染色体。一条染色体由若干基因(gene) 组成,每个基因控制一种特定的蛋白质,从而决定生物的某种特征。所有染色体合称为基因组(genome)。基因组完全决定了一个生物个体。该个体在微观(基因)层次的表现称为基因型 (genotype),在宏观(特征)层次的表现称为显型 (phenotype)。在简单的遗传算法中,将基因组中的若干条染色体看作一整条染色体。
(2) 个体复制
在复制的过程中,父母的染色体通过交叉(crossover)产生子女的染色体。染色体还可以以一定的小概率变异(mutate)。

遗传算法本质上是一种搜索算法,搜索算法的共同特征为:

  1. 首先组成一组候选解
  2. 依据某些适应性条件测算这些候选解的适应度
  3. 根据适应度保留某些候选解,放弃其他候选解
  4. 对保留的候选解进行某些操作,生成新的候选解

  
交叉(Crossover):2条染色体交换部分基因,来构造下一代的2条新的染色体。
交叉前:
00000|011100000000|10000
11100|000001111110|00101
交叉后:
00000|000001111110|10000
11100|011100000000|00101
染色体交叉是以一定的概率发生的,这个概率记为Pc 。
变异(Mutation):在繁殖过程,新产生的染色体中的基因会以一定的概率出错,称为变异。变异发生的概率记为Pm 。
变异前:
000001110000000010000
变异后:
000001110000100010000
适应度函数 ( Fitness Function ):用于评价某个染色体的适应度,用f(x)表示。有时需要区分染色体的适应度函数与问题的目标函数。例如:0-1背包问题的目标函数是所取得物品价值,但将物品价值作为染色体的适应度函数可能并不一定适合。适应度函数与目标函数是正相关的,可对目标函数作一些变形来得到适应度函数。

遗传算法伪代码

基本遗传算法伪代码
/*
* Pc:交叉发生的概率
* Pm:变异发生的概率
* M:种群规模
* G:终止进化的代数
* Tf:进化产生的任何一个个体的适应度函数超过Tf,则可以终止进化过程
*/
初始化Pm,Pc,M,G,Tf等参数。随机产生第一代种群Popdo
{ 计算种群Pop中每一个体的适应度F(i)。初始化空种群newPopdo{根据适应度以比例选择算法从种群Pop中选出2个个体if ( random ( 0 , 1 ) < Pc ){对2个个体按交叉概率Pc执行交叉操作}if ( random ( 0 , 1 ) < Pm ){对2个个体按变异概率Pm执行变异操作}
将2个新个体加入种群newPop中
} until ( M个子代被创建 )
用newPop取代Pop
}until ( 任何染色体得分超过Tf, 或繁殖代数超过G )

遗传算法优化方法:

(1)精英主义(Elitist Strategy)选择:是基本遗传算法的一种优化。为了防止进化过程中产生的最优解被交叉和变异所破坏,可以将每一代中的最优解原封不动的复制到下一代中。
(2)插入操作:可在3个基本操作的基础上增加一个插入操作。插入操作将染色体中的某个随机的片段移位到另一个随机的位置。

遗传算法实例

这里选用参考3中的实例: 计算函数

的最小值,其中每个变量的取值区间都是[-1, +1]。

首先,确定适应度的函数:

function y = my_fitness(population)
% population是随机数[0,1]矩阵,下面的操作改变范围为[-1,1]
population = 2 * (population - 0.5); 
y = sum(population.^2, 2); % 行的平方和
遗传算法实现:
function [best_fitness, elite, generation, last_generation] = my_ga( ...number_of_variables, ...    % 求解问题的参数个数fitness_function, ...       % 自定义适应度函数名population_size, ...        % 种群规模(每一代个体数目)parent_number, ...          % 每一代中保持不变的数目(除了变异)mutation_rate, ...          % 变异概率maximal_generation, ...     % 最大演化代数minimal_cost ...            % 最小目标值(函数值越小,则适应度越高)
)% 累加概率
% 假设 parent_number = 10
% 分子 parent_number:-1:1 用于生成一个数列
% 分母 sum(parent_number:-1:1) 是一个求和结果(一个数)
% 分子 10     9     8     7     6     5     4     3     2     1
% 分母 10+9+...+1=55
% 相除 0.1818    0.1636    0.1455    0.1273    0.1091    0.0909    0.0727    0.0545    0.0364    0.0182
% 累加(cumsum) 0.1818    0.3455    0.4909    0.6182    0.7273    0.8182    0.8909    0.9455    0.9818    1.0000
% 运算结果可以看出: 累加概率函数是一个从0到1增长得越来越慢的函数
cumulative_probabilities = cumsum((parent_number:-1:1) / sum(parent_number:-1:1)); % 1个长度为parent_number的数列
best_fitness = ones(maximal_generation, 1);% 记录每一代最佳适应度,先初始化为1
elite = zeros(maximal_generation, number_of_variables);% 记录每一代的最优解,初始化为0% 子女数量=种群数量 - 父母数量(父母即每一代中不发生改变的个体)
child_number = population_size - parent_number; % 每一代子女的数目% population_size 对应矩阵的行,每一行表示1个个体,行数=个体数(种群数量)
% number_of_variables 对应矩阵的列,列数=参数个数(个体特征由这些参数表示)
population = rand(population_size, number_of_variables);% 初始化种群
last_generation = 0; % 记录跳出循环时的代数for generation = 1 : maximal_generation % 演化循环开始% feval把数据带入到一个定义好的函数句柄中计算% 把population矩阵带入fitness_function函数计算cost = feval(fitness_function, population); % 计算所有个体的适应度(population_size*1的矩阵)% index记录排序后每个值原来的行数[cost, index] = sort(cost); % 将适应度函数值从小到大排序% index(1:parent_number) % 前parent_number个cost较小的个体在种群population中的行数% 选出这部分(parent_number个)个体作为父母,其实parent_number对应交叉概率population = population(index(1:parent_number), :); % 先保留一部分较优的个体% population矩阵是不断变化的% cost在经过前面的sort排序后,矩阵已经改变为升序的% cost(1)即为本代的最佳适应度best_fitness(generation) = cost(1); % 记录本代的最佳适应度% population矩阵第一行为本代的最优解(精英)elite(generation, :) = population(1, :); % 记录本代的最优解(精英)% 若本代的最优解已足够好,则停止演化if best_fitness(generation) < minimal_cost; last_generation = generation;break; end% 交叉变异产生新的种群,染色体交叉开始for child = 1:2:child_number % 步长为2是因为每一次交叉会产生2个孩子% cumulative_probabilities 长度为 parent_number% 从中随机选择2个父母出来  (child+parent_number)mother = find(cumulative_probabilities > rand, 1); % 选择一个较优秀的母亲father = find(cumulative_probabilities > rand, 1); % 选择一个较优秀的父亲% ceil:向上取整% rand 生成一个随机数% 即随机选择了一列,这一列的值交换crossover_point = ceil(rand*number_of_variables); % 随机地确定一个染色体交叉点% 假如crossover_point=3, number_of_variables=5% mask1 = 1     1     1     0     0% mask2 = 0     0     0     1     1mask1 = [ones(1, crossover_point), zeros(1, number_of_variables - crossover_point)];mask2 = not(mask1);% 获取分开的4段染色体mother_1 = mask1 .* population(mother, :); % 母亲染色体的前部分mother_2 = mask2 .* population(mother, :); % 母亲染色体的后部分father_1 = mask1 .* population(father, :); % 父亲染色体的前部分father_2 = mask2 .* population(father, :); % 父亲染色体的后部分% 得到下一代population(parent_number + child, :) = mother_1 + father_2; % 一个孩子population(parent_number+child+1, :) = mother_2 + father_1; % 另一个孩子end % 染色体交叉结束% 染色体变异开始,变异种群mutation_population = population(2:population_size, :); % 精英不参与变异,从2开始    number_of_elements = (population_size - 1) * number_of_variables; % 全部基因数目number_of_mutations = ceil(number_of_elements * mutation_rate); % 变异的基因数目(基因总数*变异率)% rand(1, number_of_mutations) 生成number_of_mutations个随机数(范围0-1)组成的矩阵(1*number_of_mutations)% 数乘后,矩阵每个元素表示发生改变的基因的位置(元素在矩阵中的一维坐标)mutation_points = ceil(number_of_elements * rand(1, number_of_mutations)); % 确定要变异的基因% 被选中的基因都被一个随机数替代,完成变异mutation_population(mutation_points) = rand(1, number_of_mutations); % 对选中的基因进行变异操作population(2:population_size, :) = mutation_population; % 发生变异之后的种群% 染色体变异结束
end % 演化循环结束
函数测试:
clc,clear all,close all;% 调用 my_ga 进行计算
% 求解问题的参数个数         10
% 自定义适应度函数名         my_fitness
% 种群规模                  100
% 每一代中保持不变的数目     50 (即交叉率0.5)
% 变异概率                  0.1 (1/10的个体发生变异)
% 最大演化代数              10000 10000代
% 最小目标值                1.0e-6 个体适应度函数值 < 0.000001结束
[best_fitness, elite, generation, last_generation] = my_ga(10, 'my_fitness', 100, 50, 0.1, 10000, 1.0e-6);% 输出后10行
disp(last_generation); 
i_begin = last_generation - 9;
disp(best_fitness(i_begin:last_generation,:));
% disp(best_fitness(9990:10000,:));
% disp(elite(9990:10000,:))
% 不要写成这样,因为GA常常在中间就跳出循环了% 将elite值转化为问题范围内
my_elite = elite(i_begin:last_generation,:);
my_elite = 2 * (my_elite - 0.5);
disp(my_elite);% 最佳适应度的演化情况
figure
loglog(1:generation, best_fitness(1:generation), 'linewidth',2)
xlabel('Generation','fontsize',15);
ylabel('Best Fitness','fontsize',15);
set(gca,'fontsize',15,'ticklength',get(gca,'ticklength')*2);% 最优解的演化情况
figure
semilogx(1 : generation, 2 * elite(1 : generation, :) - 1)
xlabel('Generation','fontsize',15);
ylabel('Best Solution','fontsize',15);
set(gca,'fontsize',15,'ticklength',get(gca,'ticklength')*2);

参考:
http://blog.jobbole.com/110913/
http://blog.csdn.net/dazhong159/article/details/7908531

http://blog.sciencenet.cn/blog-3102863-1029280.html

https://github.com/Shuai-Xie/genetic-algorithm

https://github.com/yanshengjia/artificial-intelligence/tree/master/genetic-algorithm-for-functional-maximum-problem/src



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

相关文章

遗传算法小结及算法实例(附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 中的控制項無法正確呈現實際的…

学习UpdatePanel控件-

原文可以显示图片&#xff08;转载&#xff1a;http://blog.csdn.net/ILOVEMSDN/archive/2007/11/11/1879343.aspx&#xff09; UpdatePanel控件的使用 2008-10-07 05:46 P.M. ScriptManager和UpdatePanel控件联合使用可以实现页面异步局部更新的效果。其中的UpdatePanel就是…

UpdatePanel的用法

UpdatePanel控件也是Ajax里用得最多的控件之中的一个&#xff0c;UpdatePanel控件是用来局部更新网页上的内容&#xff0c;网页上要局部更新的内容必须放在UpdatePanel控件里&#xff0c;他必须和上一次说的ScriptManager控件一起使用。如今来看UpdatePanel的属性 UpdatePanel …

浅谈UpdatePanel

这是我以前刚学习asp.net ajax的时候总结的&#xff0c;如果有什么错误的地方&#xff0c;请大家指出&#xff0c;以便我能早日改正。 1. 作用&#xff1a; UpdatePanel控件用来控制页面的局部更新&#xff0c;这些更新依赖于ScriptManager的EnablePartialRendering属性&…

UpdatePanel 控件简介

UpdatePanel 控件简介 全部折叠全部展开 代码&#xff1a;全部 代码&#xff1a;多种 代码&#xff1a;Visual Basic 代码&#xff1a;C# 代码&#xff1a;Visual C 代码&#xff1a;F# 代码&#xff1a;JScript UpdatePanel 控件简介 在本教程中&#xff0c;您将使用两…

ScriptManager updatepanel

在项目开发中&#xff0c;遇到了一个ajax更新问题&#xff0c;母版上有个通知区域&#xff08;通知区域为ajax定时更新&#xff08;updatepanel&#xff09;&#xff09;&#xff0c;上面有需要显示的几列信息&#xff0c;如最新文章数&#xff0c;批阅数&#xff0c;FTP受信状…

使用 UpdatePanel

1 概述 ASP.NET UpdatePanel 控件能让你创建丰富的、以客户为中心的 Web 应用程序。使用 UpdatePanel 控件&#xff0c;可以刷新选择的页面部分而不是使用回发来刷新整个页面&#xff0c;这就像是执行了一个局部页面更新一样。包含一个 ScriptManager 和一个或多个 UpdatePanel…

UpdatePanel控件

ASP.NET UpdatePanel控件可用于生成功能丰富、以客户端为中心的Web应用程序。通过使用UpdatePanel控件&#xff0c;可以在回发期间刷新网页的选定部分而不是刷新整个网页。这称为执行部分页更新。包含一个ScriptManager控件和一个或多个UpdatePanel控件的ASP.NET网页&#xff0…

ASP.NET AJAX入门系列(4):使用UpdatePanel控件(一)

UpdatePanel可以用来创建丰富的局部更新Web应用程序&#xff0c;它是ASP.NET 2.0 AJAX Extensions中很重要的一个控件&#xff0c;其强大之处在于不用编写任何客户端脚本&#xff0c;只要在一个页面上添加几个UpdatePanel控件和一个ScriptManager控件就可以自动实现局部更新。通…

UpdatePanel的用法及 UpdatePanel与JS冲突的解决方法

UpdatePanel的用法 ScriptManager和UpdatePanel控件联合使用可以实现页面异步局部更新的效果。其中的UpdatePanel就是设置页面中异 步局部更新区域&#xff0c;它必须依赖于ScriptManager存在&#xff0c;因为ScriptManger控件提供了客户端脚本生成与管理UpdatePanel的功 能。…