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

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

遗传算法


文章目录

  • 遗传算法
  • 前言
  • 一、遗传算法是什么?
  • 二、实例讲解
    • 例题1
      • 1.初始化种群
      • 2.优胜劣汰
      • 3.根据优胜劣汰的结果,交配生殖、变异
      • 5.生物遗传进化
    • 例题2
      • 1.初始化参数
      • 2.定义环境(定义目标函数)
      • 3.DNA解码(计算x,y)
      • 4.初始化种群(初始化解,考虑定义域)
      • 5.计算适应度(计算误差,考虑定义域)
      • 6.适者生存(挑选误差较小的答案)
      • 7.生殖、变异(更改部分二进制位,取反部分二进制位,可能生成误差更小的答案)
      • 8.查看最终的答案
      • 9.生物遗传进化
      • 10.完整代码
  • 总结


前言

因为老师布置作业,需要我们用遗传算法来求函数的最大值,因此,在网上了解了一下遗传算法,并且找到几个实例,感觉求函数最大值还是蛮简单的,重要的是把这个过程走通,目前这里是用python写的,之后会补上一篇用C语言来写的(因为作业要求用C


一、遗传算法是什么?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
简单来说,就是通过模拟生物生殖、变异,根据适者生存的原则,挑选出最后留下的生物,作为问题的最优解。一般遗传算法用于优化问题,用于解决一些求精确解是否困难的问题,例如旅行商问题,复杂函数的极值问题等等。

二、实例讲解

例题1

这个是在b站上看到的一个例子,其实是十分的简洁的。
给出链接:https://www.bilibili.com/video/BV1Yg411T7W2?spm_id_from=333.1007.top_right_bar_window_history.content.click
问题描述:在一个长度为n的数组nums中选择10个元素,使得10个元素的和与原数组的所有元素之和的1/10无限接近。
如n=50, sum(nums)=1000, 选择元素列表answer要满足|sum(answer)-100|<e,e尽可能小。

1.初始化种群

生成50个范围从0到1000的随机数。

import random
def create_answer(number_set, n):  # 随机选择n个数作为答案,据题意选择n=10result = []for i in range(n):result.append(random.sample(number_set, 10))return resultnumber_set = random.sample(range(0, 1000), 50)
middle_answer = create_answer(number_set, 100)  # 随机选择100个答案(种群)

2.优胜劣汰

计算每个答案与正确答案的偏离程度,计算适应度(错误率

def error_level(new_answer, number_set):  # 计算错误率,错误率越小遗传的概率越大error = []right_answer = sum(number_set) / 10for item in new_answer:value = abs(right_answer - sum(item))if value == 0:error.append(10)else:error.append(1 / value)return error

3.根据优胜劣汰的结果,交配生殖、变异

def variation(old_answer, number_set, pro):  # 0.1的变异概率for i in range(len(old_answer)):rand = random.uniform(0, 1)if rand < pro:rand_num = random.randint(0, 9)old_answer[i] = old_answer[i][:rand_num] + random.sample(number_set, 1) + old_answer[i][rand_num+1:]return old_answerdef choice_selected(old_answer, number_set):  # 交叉互换模拟交配生殖的结果result = []error = error_level(old_answer, number_set)error_one = [item / sum(error) for item in error]for i in range(1, len(error_one)):error_one[i] += error_one[i - 1]for i in range(len(old_answer) // 2):temp = []for j in range(2):rand = random.uniform(0, 1)for k in range(len(error_one)):if k == 0:if rand < error_one[k]:temp.append(old_answer[k])else:if rand >= error_one[k-1] and rand < error_one[k]:temp.append(old_answer[k])rand = random.randint(0, 6)temp_1 = temp[0][:rand] + temp[1][rand:rand+3] + temp[0][rand+3:]temp_2 = temp[1][:rand] + temp[0][rand:rand+3] + temp[1][rand+3:]result.append(temp_1)result.append(temp_2)return result

5.生物遗传进化

number_set = random.sample(range(0, 1000), 50)
middle_answer = create_answer(number_set, 100)
first_answer = middle_answer[0]
greater_answer = []
for i in range(1000): #error = error_level(middle_answer, number_set)  # 计算适应度index = error.index(max(error))middle_answer = choice_selected(middle_answer, number_set)middle_answer = variation(middle_answer, number_set, 0.1)greater_answer.append([middle_answer[index], error[index]])greater_answer.sort(key=lambda x: x[1], reverse=True)
print("正确答案为", sum(number_set) / 10)
print("给出最优解为", greater_answer[0][0])
print("该和为", sum(greater_answer[0][0]))
print("选择系数为", greater_answer[0][1])
print("最初解的和为", sum(first_answer))for i in greater_answer[0][0]:if i in number_set:print(i)

运行结果(不定:
在这里插入图片描述
这个是我开始学习遗传算法最开始学的一个例题,其实现在回过头来看,这个代码其实写的通用性并不强,并且核心思想并不突出,例如DNA的概念并不强,可能是题目类型不同,和求复杂函数极值问题的代码还是有些差别的,但是遗传算法的思想本质是有的,因此拿来讲讲。

例题2

遗传算法详解 附python代码实现
这就是一个是用遗传算法求函数极值的例子,里面有可视化,有代码,还是挺不错的,用上了numpy矩阵运算,效率十分不错,不过我感觉对于初学者来说可能有点难理解,而且我感觉里面对于DNA编码解码的那块有点问题,实际上直接使用二进制转换为十进制就可以了。因此,我参考这篇博客,自己重新写了一遍代码。下面将讲解我的代码思路。

1.初始化参数

我是将DNA组合为animal模拟一个生物,然后每个DNA用二进制编码,DNA_bit是表示一个DNA的大小由符号位(1位)+数据位组成,数据位由整数位和小数位组成。
DNA数据位中Int_bit则表示整数的位数,例如Int_bit=2则表示整数部分为00-11,转换为十进制就是0-3。
DNA_num则表示一个animal有多少个DNA,每条DNA都是DNA_bit大小,可以理解为能够表示几个数,这里有两个数x,y,因此两个DNA就足够了。
剩下参数应该好理解。

import numpy as np
import mathDNA_bit = 13 # 一个DNA的二进制位数,(第一维表示符号位)
Int_bit = 2  # DNA_bit-1(符号位bit)之后整数占的bit位
DNA_num = 2  # DNA的个数
animal_num = 200 # 开始种群的数量 
cross_rate = 0.8 # 生殖交叉概率
variation_rate = 0.005  # 变异的概率
generator_n = 50 # 种群演变的次数
limit_area = [-3, 3] # 值域

2.定义环境(定义目标函数)

这题就是求这个复杂函数的最大值,模拟生物生存的环境

def f(x, y):return 3*(1-x)**2*np.exp(-(x**2)-(y+1)**2)- 10*(x/5 - x**3 - y**5)*np.exp(-x**2-y**2)- 1/3**np.exp(-(x+1)**2 - y**2)

3.DNA解码(计算x,y)

这个函数每次传入的是一个animal即两个DNA的组合,解码出来的结果就是所表示的x,y

def translate_DNA(animal):  # 解码种群的DNAdef DNA2t10(DNA):sum = 0sign = DNA[0]data = DNA[1:]if sign == 0:  # 符号位赋值flag = -1else:flag = 1for i in range(0, Int_bit):if data[i] == 1:sum += math.pow(2, Int_bit - i - 1)for i in range(Int_bit, len(data)):if data[i] == 1:sum += math.pow(2, Int_bit - i - 1)return flag * sumDNA_result = []for i in range(0, DNA_bit * DNA_num, DNA_bit):DNA = animal[i:i+DNA_bit]translated_DNA = DNA2t10(DNA)DNA_result.append(translated_DNA)return DNA_result

4.初始化种群(初始化解,考虑定义域)

由于可能由定义域的限制,因此在初始化种群的时候,确保所有的种群都符合定义域(大环境)

def flag_limit_area(animal, limit_area):  # 判断种群是否符合值域,否则一票否决x, y = translate_DNA(animal)if x <= limit_area[1] and x >= limit_area[0] and y <= limit_area[1] and y >= limit_area[0]:return Trueelse:return False# 初始化种群,需要判断开始的种群是否符合值域
animals = np.random.randint(2, size=(animal_num, DNA_bit * DNA_num))
# 每个animal由两个DNA组成,每个DNA为DNA_bit位num = animal_num
while(num):pos = num - 1if flag_limit_area(animals[pos], limit_area):num -= 1else:animals[pos] = np.random.randint(2, size=(1, DNA_bit * DNA_num))

5.计算适应度(计算误差,考虑定义域)

根据目标函数,计算出误差,由于这里是要求最大值,因此带入函数结果越大,适应度也就越大。这里需要考虑是否符合定义域的情况,不符合一票否决。

def get_fitness(animals):  # 计算种群各个部分的适应度fitness_score = np.zeros(len(animals))fit_flag = np.zeros(len(animals))for i in range(len(animals)):x, y = translate_DNA(animals[i])fitness_score[i] = f(x, y)if flag_limit_area(animals[i], limit_area):fit_flag[i] = 1else:fit_flag[i] = 0fitness_score = (fitness_score - np.min(fitness_score)) + 1e-5fitness_score = fitness_score * fit_flag # 如果不符合定义域就不取了fitness_p = fitness_score / (fitness_score.sum())  # 计算被选择的概率return fitness_p 

6.适者生存(挑选误差较小的答案)

根据之前的适应度的结果,误差越小适应度大,可以转换为概率,因此被留下的概率也就越大。

def select_animal(animals, fitness):  # 按照适应度选择留下的种群idx = np.random.choice(np.arange(animal_num), size=animal_num, replace=True, p=(fitness)/(fitness.sum() + 1e-8))return animals[idx]

7.生殖、变异(更改部分二进制位,取反部分二进制位,可能生成误差更小的答案)

def variation(children, variation_rate):  # 模拟编译if np.random.rand() < variation_rate: #以MUTATION_RATE的概率进行变异mutate_point = np.random.randint(0, DNA_bit * 2)  # 随机产生一个实数,代表要变异基因的位置children[mutate_point] = children[mutate_point] ^ 1  #这一位取反return childrendef crossover_and_variation(animals, cross_rate):  # 模拟生殖过程(包括交配和变异)new_animals = []for father in animals:child = father		# 选择父亲if np.random.rand() < cross_rate:	#产生子代时不是必然发生交叉,而是以一定的概率发生交叉mother = animals[np.random.randint(animal_num)]	#再选择母亲cross_points = np.random.randint(low = 0, high = DNA_bit * DNA_num)	#随机产生交叉的点child[cross_points:] = mother[cross_points:] # 交叉互换,模拟生殖variation(child, variation_rate)	#变异new_animals.append(child)return np.array(new_animals)

8.查看最终的答案

def get_result(animals):  # 获取结果fitness = get_fitness(animals)max_fitness_index = np.argmax(fitness)print("max_fitness:", fitness[max_fitness_index])x, y = translate_DNA(animals[max_fitness_index])print("最优的基因型:", animals[max_fitness_index])print("(x, y):", (x, y), f(x, y))return

9.生物遗传进化

# 模拟进化选择generator_n轮    
for i in range(generator_n):fitness_score = get_fitness(animals)  # 计算适应度selected_animals = select_animal(animals, fitness_score) # 适者生存animals = crossover_and_variation(selected_animals, cross_rate)  # 生殖、变异

10.完整代码

import numpy as np
import mathDNA_bit = 13 # 一个DNA的二进制位数,(第一维表示符号位)
Int_bit = 2  # DNA_bit-1(符号位bit)之后整数占的bit位
DNA_num = 2  # DNA的个数
animal_num = 200 # 开始种群的数量 
cross_rate = 0.8 # 生殖交叉概率
variation_rate = 0.005  # 变异的概率
generator_n = 50 # 种群演变的次数
limit_area = [-3, 3]def f(x, y):return 3*(1-x)**2*np.exp(-(x**2)-(y+1)**2)- 10*(x/5 - x**3 - y**5)*np.exp(-x**2-y**2)- 1/3**np.exp(-(x+1)**2 - y**2)def translate_DNA(animal):  # 解码种群的DNAdef DNA2t10(DNA):sum = 0sign = DNA[0]data = DNA[1:]if sign == 0:  # 符号位赋值flag = -1else:flag = 1for i in range(0, Int_bit):if data[i] == 1:sum += math.pow(2, Int_bit - i - 1)for i in range(Int_bit, len(data)):if data[i] == 1:sum += math.pow(2, Int_bit - i - 1)return flag * sumDNA_result = []for i in range(0, DNA_bit * DNA_num, DNA_bit):DNA = animal[i:i+DNA_bit]translated_DNA = DNA2t10(DNA)DNA_result.append(translated_DNA)return DNA_resultdef flag_limit_area(animal, limit_area):  # 判断种群是否符合值域,否则一票否决x, y = translate_DNA(animal)if x <= limit_area[1] and x >= limit_area[0] and y <= limit_area[1] and y >= limit_area[0]:return Trueelse:return Falsedef get_fitness(animals):  # 计算种群各个部分的适应度fitness_score = np.zeros(len(animals))fit_flag = np.zeros(len(animals))for i in range(len(animals)):x, y = translate_DNA(animals[i])fitness_score[i] = f(x, y)if flag_limit_area(animals[i], limit_area):fit_flag[i] = 1else:fit_flag[i] = 0fitness_score = (fitness_score - np.min(fitness_score)) + 1e-5fitness_score = fitness_score * fit_flag # 如果不符合定义域就不取了fitness_p = fitness_score / (fitness_score.sum())  # 计算被选择的概率return fitness_p def select_animal(animals, fitness):  # 按照适应度选择留下的种群idx = np.random.choice(np.arange(animal_num), size=animal_num, replace=True, p=(fitness)/(fitness.sum() + 1e-8))return animals[idx]def variation(children, variation_rate):  # 模拟编译if np.random.rand() < variation_rate: #以MUTATION_RATE的概率进行变异mutate_point = np.random.randint(0, DNA_bit * 2)  # 随机产生一个实数,代表要变异基因的位置children[mutate_point] = children[mutate_point] ^ 1  #这一位取反return childrendef crossover_and_variation(animals, cross_rate):  # 模拟生殖过程(包括交配和变异)new_animals = []for father in animals:child = father		# 选择父亲if np.random.rand() < cross_rate:	#产生子代时不是必然发生交叉,而是以一定的概率发生交叉mother = animals[np.random.randint(animal_num)]	#再选择母亲cross_points = np.random.randint(low = 0, high = DNA_bit * DNA_num)	#随机产生交叉的点child[cross_points:] = mother[cross_points:] # 交叉互换,模拟生殖variation(child, variation_rate)	#变异new_animals.append(child)return np.array(new_animals)def get_result(animals):  # 获取结果fitness = get_fitness(animals)max_fitness_index = np.argmax(fitness)print("max_fitness:", fitness[max_fitness_index])x, y = translate_DNA(animals[max_fitness_index])print("最优的基因型:", animals[max_fitness_index])print("(x, y):", (x, y), f(x, y))return# 初始化种群,需要判断开始的种群是否符合值域
animals = np.random.randint(2, size=(animal_num, DNA_bit * DNA_num))
num = animal_num
while(num):pos = num - 1if flag_limit_area(animals[pos], limit_area):num -= 1else:animals[pos] = np.random.randint(2, size=(1, DNA_bit * DNA_num))# 模拟进化选择generator_n轮    
for i in range(generator_n):fitness_score = get_fitness(animals)selected_animals = select_animal(animals, fitness_score)animals = crossover_and_variation(selected_animals, cross_rate)get_result(animals)

运行结果(不定:
在这里插入图片描述
这里因为是我自己写的,亲儿子,所有我会觉得比较好理解,就是没有使用矩阵乘法,可能速度会有点问题,但是,初学者理解起来应该会比较简单,没事,哪里有问题改哪里就好了。

总结

遗传算法的大概思路就是模拟生物的优胜劣汰、适者生存,还是很生动形象,因为是比较简单的例子,可能代码还是会有很多地方考虑步骤,但是对我的作业来说还是足够了。
作业如下
在这里插入图片描述
在这里插入图片描述
代码我就不贴了,上面随便改改就好了,这是我的运行结果,你们可以试试。


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

相关文章

遗传算法实例解析

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

学习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 …