优化算法---遗传算法

目录

  • 一、基本定义
    • 1.1 遗传与变异
    • 1.2 进化
  • 二、算法简介
    • 2.1 基本原理
    • 2.2 算法步骤
    • 2.3 算法案例
      • 2.3.1 最大值求解
      • 2.3.2 旅行商问题求解
    • 2.4 算法优缺点

优化算法—模拟退火算法
优化算法—遗传算法

一、基本定义

  遗传算法(Genetic Algorithm,GA)是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法,借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种高效、并行、全局搜索的方法,能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最佳解。

1.1 遗传与变异

  构成生物的基本结构和功能单位是细胞(Cell)。细胞中含有的一种微小的丝状化合物称为染色体(Chromosome),生物的所有遗传信息都包含在这个复杂而又微小的染色体中。遗传信息是由基因组成,生物的各种性状由其相应的基因所控制,基因是遗传的基本单位。细胞通过分裂具有自我复制的能力,在细胞分裂的过程中,其遗传基因也同时被复制到下一代从而其性状也被下一代所继承。
  细胞在分裂时,遗传物质DNA通过复制(Reproduction)而转移到新产生的细胞中,新细胞就继承了旧细胞的基因。有性生殖生物在繁殖下一代时,两个同源染色体之间通过交叉(Crossover)而重组,即在两个染色体的某一相同位置处DNA被切断,其前后两串分别交叉组合而形成两个新的染色体。另外,在进行细胞复制时,虽然概率很小,但也有可能产生某些复制差错,从而使DNA发生某种变异(Mutation),产生出新的染色体。
在这里插入图片描述

1.2 进化

  生物在其延续生存的过程中,逐渐适应于其生存环境,使得其品质不断得到改良,这种生命现象称为进化(Evolution)。生物的进化是以集团的形式共同进行的,这样的一个团体称为群体(Population),组成群体的单个生物称为个体(Individual),每一个个体对其生存环境都有不同的适应能力(解决问题的好坏),这种适应能力称为个体的适应度(Fitness)。
核心
1.种群的交配、繁衍后代:遗传与变异
2.自然的选择:根据适应度进行选择,保留优质个体并淘汰劣质个体。
目标:通过多次模拟生物进化,让种群逐步向更优的解进化,直到找到问题的最佳解或接近最优解。

二、算法简介

2.1 基本原理

  生物的进化过程主要是通过染色体之间的交叉和染色体的变异来完成的,与此相对应,遗传算法中最优解的搜索过程也模仿生物的这个进化过程,使用所谓的遗传算子作用于群体 P ( t ) P(t) P(t)中,进行下述遗传操作,从而得到新一代群体 P ( t + 1 ) P(t+1) P(t+1)

  • 选择: 根据各个个体的适应度(函数),按照一定的规则或方法,从第 t t t代群体 P ( t ) P(t) P(t)中选择出一些优良的个体遗传到下一代群体 P ( t + 1 ) P(t+1) P(t+1)中。
  • 交叉: 将群体 P ( t ) P(t) P(t)内的各个个体随机搭配成对,对每一对个体,以某个概率(称为交叉概率,crossover rate)交换它们之间的部分染色体。
  • 变异: 对群体 P ( t ) P(t) P(t)中的每一个个体,以某概率(称为变异概率,mutation rate)改变某一个或某一些基因座上的基因值为其他的等位基因。

2.2 算法步骤

1、初始化种群
随机生成一组“解”,即多个“个体”,这些个体组成了“种群”。
每个个体由一串基因编码表示(可以是二进制、实数或其他形式)。
2、评估适应度
对每个个体进行评估,计算其“适应度”,即这个解有多好。适应度越高表示解越优。
3、选择(自然选择)
根据适应度选择“优秀个体”作为父代,淘汰适应度低的个体。
模仿自然界优胜劣汰的过程,让优秀个体更有可能传递自己的基因。
4、交叉(基因重组)
从选出的父代中随机挑选两名“父母”,交换它们的部分基因,产生“子代”。比如,将两个个体基因的一部分互换,模拟生物繁殖。
5、变异(基因变异)
随机改变某些个体的基因(比如基因翻转0变1或1变0),模拟基因突变现象。
突变可以防止算法陷入局部最优,增加探索新解的能力。
6、迭代进化
重复以上步骤(选择、交叉、突变),让种群逐代进化,不断提高整体适应度。
7、停止条件
当达到设定的迭代次数或适应度达到期望值时,停止进化并输出最优解。
在这里插入图片描述

2.3 算法案例

2.3.1 最大值求解

  将个体适应度大小映射为概率进行复制:适应度高的个体有更大概率复制,且复制的份数越条——轮盘赌法

import random

# 1. 初始化种群
def init_population(pop_size, gene_length):
    # 初始化一个种群,种群中有 pop_size 个个体,每个个体是一个随机整数,表示基因值
    # 基因长度 gene_length 决定了基因的取值范围 (0 到 2^gene_length - 1)
    return [random.randint(0, 2**gene_length - 1) for _ in range(pop_size)]

# 2. 适应度函数
def fitness(x):
    # 适应度函数:这里我们以 x 的平方作为适应度,目标是最大化 f(x) = x^2
    return x**2

# 3. 选择操作(轮盘赌选择)
def selection(population, fitness_scores):
    # 计算适应度的总和
    total_fitness = sum(fitness_scores)
    
    # 计算每个个体被选中的概率,适应度越高,被选中的概率越大
    prob = [f / total_fitness for f in fitness_scores]
    
    # 使用轮盘赌选择法,按照适应度概率选择两个父母
    selected = random.choices(population, prob, k=2)
    
    # 返回选中的两个父母
    return selected

# 4. 交叉操作(单点交叉)
def crossover(parent1, parent2, crossover_rate=0.7, gene_length=5):
    # 判断是否进行交叉操作,交叉概率为 crossover_rate(默认为 70%)
    if random.random() < crossover_rate:
        # 随机选择一个交叉点(基因长度范围内)
        point = random.randint(1, gene_length - 1)
        
        # 使用位操作实现交叉
        mask = (1 << point) - 1  # 生成一个掩码,用于分割基因
        # child1 和 child2 是交叉后的两个子代个体
        child1 = (parent1 & mask) | (parent2 & ~mask)  # 从 parent1 和 parent2 中选取基因
        child2 = (parent2 & mask) | (parent1 & ~mask)
        
        # 将交叉后的基因限制在 [0, 31] 范围内(即 gene_length 位的范围)
        child1 = child1 % (2**gene_length)
        child2 = child2 % (2**gene_length)
        
        # 返回交叉生成的两个子代个体
        return child1, child2
    else:
        # 如果没有进行交叉,直接返回父代个体
        return parent1, parent2

# 5. 突变操作
def mutation(child, mutation_rate=0.01, gene_length=5):
    # 判断是否进行突变操作,突变概率为 mutation_rate(默认为 1%)
    if random.random() < mutation_rate:
        # 随机选择一个基因位点进行突变
        point = random.randint(0, gene_length - 1)
        
        # 通过异或操作对基因进行突变
        child ^= (1 << point)  # 翻转该位置的基因
        
        # 确保突变后的基因值在 [0, 31] 范围内
        child = child % (2**gene_length)
    
    # 返回突变后的个体
    return child

# 6. 遗传算法主循环
def genetic_algorithm(pop_size, gene_length, generations):
    # 初始化种群
    population = init_population(pop_size, gene_length)
    
    # 用于追踪当前最优个体
    best_individual = None
    best_fitness_value = -1  # 初始适应度设置为一个较小值
    
    # 迭代多代
    for generation in range(generations):
        # 计算每个个体的适应度
        fitness_scores = [fitness(individual) for individual in population]
        
        # 找到当前种群中的最优个体
        max_fitness = max(fitness_scores)
        max_fitness_index = fitness_scores.index(max_fitness)
        
        # 如果当前最优个体的适应度大于历史最优适应度,则更新最优个体
        if max_fitness > best_fitness_value:
            best_fitness_value = max_fitness
            best_individual = population[max_fitness_index]

        # 打印当前代数和最优个体及其适应度
        print(f"Generation {generation}: Best individual = {best_individual}, Fitness = {best_fitness_value}")
        
        # 创建新一代种群
        new_population = []
        
        # 保证最优个体进入新一代
        new_population.append(best_individual)
        
        # 进行选择、交叉、突变生成新的个体,直到新种群满员
        while len(new_population) < pop_size:
            # 选择两个父代个体
            parent1, parent2 = selection(population, fitness_scores)
            
            # 对父代个体进行交叉操作,生成两个子代个体
            child1, child2 = crossover(parent1, parent2, gene_length=gene_length)
            
            # 对子代个体进行突变操作
            new_population.append(mutation(child1, gene_length=gene_length))
            
            # 确保新种群的个体数量不会超过 pop_size
            if len(new_population) < pop_size:
                new_population.append(mutation(child2, gene_length=gene_length))
        
        # 更新种群为新生成的种群
        population = new_population
    
    # 返回最优个体和最优适应度
    return best_individual, best_fitness_value

# 7. 设置参数并运行算法
pop_size = 100  # 种群大小
gene_length = 5  # 基因长度(表示0到31之间的数)
generations = 50  # 迭代代数

# 运行遗传算法,得到最优个体及其适应度
best_individual, best_fitness = genetic_algorithm(pop_size, gene_length, generations)

# 打印最终找到的最优解
print(f"\nOptimal solution found: x = {best_individual}, f(x) = {best_fitness}")

在这里插入图片描述

2.3.2 旅行商问题求解

import random
import numpy as np

# 1. 计算城市间的距离
def calculate_distance(city1, city2):
    # 假设城市坐标为二维坐标
    return np.sqrt((city1[0] - city2[0])**2 + (city1[1] - city2[1])**2)

# 2. 初始化种群
def init_population(pop_size, num_cities):
    # 生成初始种群,每个个体是一个城市的访问顺序(城市的索引)
    population = []
    for _ in range(pop_size):
        individual = list(range(num_cities))
        random.shuffle(individual)
        population.append(individual)
    return population

# 3. 计算个体的适应度(路径长度)
def fitness(individual, cities):
    total_distance = 0
    # 计算路径总长度
    for i in range(len(individual) - 1):
        total_distance += calculate_distance(cities[individual[i]], cities[individual[i + 1]])
    # 加上从最后一个城市返回到起点的距离
    total_distance += calculate_distance(cities[individual[-1]], cities[individual[0]])
    return total_distance

# 4. 选择操作(轮盘赌选择)
def selection(population, fitness_scores):
    total_fitness = sum(fitness_scores)
    prob = [1 / f for f in fitness_scores]  # 使用倒数适应度,适应度小的个体更适合选择
    prob = [p / sum(prob) for p in prob]  # 归一化
    selected = random.choices(population, prob, k=2)
    return selected

# 5. 交叉操作(部分匹配交叉 PMX)
def crossover(parent1, parent2):
    # 随机选择交叉区间
    start, end = sorted(random.sample(range(len(parent1)), 2))
    
    # 创建子代,子代初始化为父代1的副本
    child1 = [-1] * len(parent1)
    child2 = [-1] * len(parent1)

    # 将父代的交叉区间拷贝到子代中
    child1[start:end+1] = parent1[start:end+1]
    child2[start:end+1] = parent2[start:end+1]

    # 对于子代的其余部分,填充剩余的城市,保持顺序
    def fill_child(child, parent, other_parent):
        for i in range(len(parent)):
            if child[i] == -1:
                gene = parent[i]
                while gene in child:  # 如果该基因已经存在于子代中,跳过
                    gene = other_parent[other_parent.index(gene) + 1]
                child[i] = gene
        return child

    child1 = fill_child(child1, parent1, parent2)
    child2 = fill_child(child2, parent2, parent1)
    
    return child1, child2

# 6. 突变操作(交换突变)
def mutation(child, mutation_rate=0.02):
    if random.random() < mutation_rate:
        # 随机选择两个城市交换位置
        i, j = random.sample(range(len(child)), 2)
        child[i], child[j] = child[j], child[i]
    return child

# 7. 遗传算法主循环
def genetic_algorithm(cities, pop_size=100, generations=500, mutation_rate=0.02):
    num_cities = len(cities)
    
    # 初始化种群
    population = init_population(pop_size, num_cities)
    
    best_individual = None
    best_fitness_value = float('inf')  # 用于追踪最优个体
    
    for generation in range(generations):
        # 计算种群中每个个体的适应度
        fitness_scores = [fitness(individual, cities) for individual in population]
        
        # 找到当前最优解
        min_fitness = min(fitness_scores)
        min_fitness_index = fitness_scores.index(min_fitness)
        if min_fitness < best_fitness_value:
            best_fitness_value = min_fitness
            best_individual = population[min_fitness_index]
        
        # 打印当前代和最优适应度
        print(f"Generation {generation}: Best fitness = {best_fitness_value}")
        
        # 创建新种群
        new_population = []
        
        # 保证最优个体进入新一代
        new_population.append(best_individual)
        
        # 进行选择、交叉、突变生成新的个体
        while len(new_population) < pop_size:
            parent1, parent2 = selection(population, fitness_scores)
            child1, child2 = crossover(parent1, parent2)
            new_population.append(mutation(child1, mutation_rate))
            if len(new_population) < pop_size:
                new_population.append(mutation(child2, mutation_rate))
        
        # 更新种群为新生成的种群
        population = new_population
    
    return best_individual, best_fitness_value

# 8. 设置参数并运行算法
# 城市位置:每个城市的坐标是一个二维点
cities = [(0, 0), (1, 3), (4, 3), (6, 1), (3, 0), (5, 5), (7, 2)]

best_individual, best_fitness = genetic_algorithm(cities, pop_size=100, generations=500)
print(f"\nOptimal solution found: Path = {best_individual}, Distance = {best_fitness}")

在这里插入图片描述

2.4 算法优缺点

优点
1、通用性强:适合解决各种复杂优化问题,不需要知道问题的数学性质。
2、全局搜索能力强:不会陷入局部最优解,探索能力较强。
3、易于并行计算:可以多线程或分布式运行。
缺点
1、计算复杂度高:大规模问题时计算量较大。
2、参数敏感性强:需要调整交叉率、突变率等参数才能达到最优效果。
3、早熟收敛:可能在局部最优点附近停滞,难以进一步优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/949329.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

匠人天工Ai浮雕网站创新发布了ZBrush插件,提效500%,为AI+数字雕刻行业带来新的活力

2025年1月6日&#xff0c;杭州——杭州仓颉造梦数字科技公司旗下产品匠人天工近日宣布推出一款创新的ZBrush插件&#xff0c;旨在为AI数字雕刻行业带来前所未有的效率提升。该插件通过一系列智能化功能&#xff0c;大幅简化了数字雕刻的建模流程&#xff0c;使建模效率提高了50…

NV256H语音提示芯片助力自动洗车机更加智能化!

汽车保养是每位车主日常生活中不可或缺的一部分&#xff0c;而洗车作为保养的基本环节&#xff0c;其便捷性和智能化程度正逐渐成为消费者选择的重要考量。在这样的背景下&#xff0c;全自动洗车机应运而生&#xff0c;并被广泛应用于汽车美容行业。 因为是全自动洗车模式&…

NLP CH3复习

CH3 3.1 几种损失函数 3.2 激活函数性质 3.3 哪几种激活函数会发生梯度消失 3.4 为什么会梯度消失 3.5 如何解决梯度消失和过拟合 3.6 梯度下降的区别 3.6.1 梯度下降&#xff08;GD&#xff09; 全批量&#xff1a;在每次迭代中使用全部数据来计算损失函数的梯度。计算成本…

关于蔬菜商品的预测定价计算【数值计算课设】

源码+报告 下载链接在文章末尾。 文章目录 源码+报告蔬菜类商品的自动定价与补货决策1 引 言2 题目描述3 问题解决3.1 模型的建立与求解3.2 算法3.2.1 非线性算法3.2.2 ARMA算法3.2.3 粒子群算法4 结论参考文献下载链接蔬菜类商品的自动定价与补货决策 [摘 要] 蔬菜商品的补货…

adb使用及常用命令

目录 介绍 组成 启用adb调试 常用命令 连接设备 版本信息 安装应用 卸载应用 文件操作 日志查看 屏幕截图和录制 设备重启 端口转发 调试相关 设置属性 设备信息查询 获取帮助 模拟输入 介绍 adb全称为 Android Debug Bridge(Android调试桥)&#xff0c;是 A…

y7000p2023AX211ubuntu20无线网卡驱动

网卡检测 查看无线网卡驱动,本教程适用的网卡为Intel Corporation Device[8086:51f1],即AX211 lspci -nn | grep Net这里的Ethernet controller是有线网卡&#xff0c;Network controller是无线网卡&#xff0c;Intel corporation Device指英伟达网卡对应的设备号是[8086:51f1]…

链表OJ题(一)

(一&#xff09;轮转数组 . - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a;给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例一&#xff1a; 方法一&#xff1a;暴力求解 先用一个变量存储数组中的最后…

Python如何精准定位并修改MP4文件的mvhd原子

深入了解MP4文件的结构对于安全地修改元数据非常重要。MP4文件采用基于原子&#xff08;atom&#xff09;的结构组织数据&#xff0c;每个原子代表一种特定的信息或数据块。例如&#xff0c;moov原子包含了视频的元数据信息&#xff0c;mvhd原子包含了视频的头信息&#xff0c;…

[SMARTFORMS] 系统变量的使用

在PAGE1页面节点下创建WINDOW5窗口 填写WINDOW5窗口描述以及位置&#xff0c;大小等相关信息 在WINDOW5窗口节点下新建TEMPLATE模板 为TEMPLATE模板设置行列相关信息 在TEMPLATE模板节点下面新增3个TEXT文本 每个TEXT文本的内容如下所示&#xff1a; %TEXT25 打印日期文本内容 …

C盘清理方法大全

目录 方法1&#xff1a;系统磁盘清理 方法2&#xff1a;找到存储删除 方法3&#xff1a;使用第三方软件Dism 方法4&#xff1a;关闭虚拟内存功能 方法5&#xff1a;磁盘分区扩展 方法1&#xff1a;系统磁盘清理 第一步&#xff1a;「此电脑 」- 「本地磁盘C」&#xff0c…

计算机的错误计算(二百零三)

摘要 利用两个大模型化简计算 其中一个大模型是数学解题器&#xff0c;它通过化简得出了正确结果&#xff1b;另外一个大模型给出了 Python代码。 例1. 化简计算摘要中算式。 下面是一个数学解题器大模型给的回答。 以上是数学解题器大模型给的回答。 下面是与另外一个大模型…

【JVM】总结篇之GC日志分析 和 案例

文章目录 GC日志参数GC日志格式GC日志分类MinorGCFullGC 文件概念 OOMOOM案例1&#xff1a;堆溢出OOM案例2&#xff1a;元空间溢出OOM案例3&#xff1a;GC overhead limit exceededOOM案例4&#xff1a;线程溢出 GC日志参数 GC日志格式 GC日志分类 MinorGC MinorGC(或young …

ASP.NET Core 中服务生命周期详解:Scoped、Transient 和 Singleton 的业务场景分析

前言 在 ASP.NET Core 中&#xff0c;服务的生命周期直接影响应用的性能和行为。通过依赖注入容器 (Dependency Injection, DI)&#xff0c;我们可以为服务定义其生命周期&#xff1a;Scoped、Transient 和 Singleton。本文将详细阐述这些生命周期的区别及其在实际业务中的应用…

Redis中字符串和列表的区别

在 Redis 中&#xff0c;字符串&#xff08;String&#xff09;和列表&#xff08;List&#xff09;是两种截然不同的数据类型&#xff0c;它们各自有着独特的特点和适用场景。 数据结构 • 字符串&#xff08;String&#xff09;&#xff1a; • 在 Redis 中&#xff0c;字符串…

正则表达式{}和(),pyhton里的正则表达式,函数findall解析

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 正则…

Angular由一个bug说起之十三:Cross Origin

跨域 想要了解跨域&#xff0c;首要要了解源 什么是源&#xff0c;源等于协议加域名加端口号 只有这三个都相同&#xff0c;才是同源&#xff0c;反之则是非同源。 比如下面这四个里&#xff0c;只有第4个是同源 而浏览器给服务器发送请求时&#xff0c;他们的源一样&#xff0…

x86霸权难动摇!

快科技1月6日消息&#xff0c;根据市场研究机构ABI Research的最新报告&#xff0c;尽管2025年被视为Arm PC市场扩张的关键一年&#xff0c;但搭载Arm架构处理器的PC预计仅占PC总出货量的13%。 ABI Research的分析师指出&#xff0c;尽管高通最新的PC处理器在性能和AI功能上有…

STM32的LED点亮教程:使用HAL库与Proteus仿真

学习目标&#xff1a;掌握使用STM32 HAL库点亮LED灯&#xff0c;并通过Proteus进行仿真验证&#xff01; 建立HAL库标准工程 1.新建工程文件夹 新建工程文件夹建议路径尽量为中文。建立文件夹的目的为了更好分类去管理项目工程中需要的各类工程文件。 首先需要在某个位置建立工…

mongodb==安装prisma连接

官网下载mongodb,解压安装 Download MongoDB Community Server | MongoDB 修改bin/mongod.cfg # mongod.conf# for documentation of all options, see: # http://docs.mongodb.org/manual/reference/configuration-options/# Where and how to store data. storage:dbPat…

前端工程化之手搓webpack5 --【elpis全栈项目】

前端工程化之手搓webpack5 --【elpis全栈项目】 导读 基本流程&#xff1a;输入 – 编译 – 输出 #mermaid-svg-V8Gi7RFNikCuEhax {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-V8Gi7RFNikCuEhax .error-icon{fil…