【计算智能】基本遗传算法在优化问题中的应用与实验【理论到程序】

news2024/11/20 14:32:03

文章目录

  • 1. 引言:遗传算法简介
  • 2. 基本遗传算法(SGA)
    • 2.1 基本遗传算法的构成要素
      • 1. 染色体编码
      • 2. 适应度函数
      • 3. 遗传算子
    • 2.2 实验设计与方法
      • 1. 算法流程
      • 2. 伪代码
      • 3. python实现
        • 1. 导入模块
        • 2. 目标函数 f(x)
        • 3 初始化种群
        • 4. 计算适应度
        • 5. 选择操作:轮盘赌选择
        • 6. 单点交叉操作
        • 7. 变异操作
        • 8. 遗传算法
        • 9. 主程序
    • 2.3 实验结果与分析
    • 2.4 结论与展望
  • 3. 遗传算法的改进
  • 4. 遗传算法的应用
  • 5. 代码整合
    • 6. 随笔

摘要: 本文将介绍遗传算法在解决优化问题中的应用,并通过实验展示了遗传算法的基本原理和实现过程。选取一个简单的二次函数作为优化目标,利用遗传算法寻找其在指定范围内的最大值。

1. 引言:遗传算法简介

  遗传算法是一种启发式优化算法,模拟了生物进化的过程,通过选择、交叉和变异等操作来搜索解空间中的最优解或近似解,其在解决复杂的优化问题和搜索空间较大的问题时表现出色。

2. 基本遗传算法(SGA)

  基本遗传算法(Simple Genetic Algorithm : SGA)又称为简单遗传算法,只使用选择算子、交叉算子和变异算子这三种基本的遗传算子。其遗传操作简单、容易理解,是其它遗传算法的雏形和基础。

2.1 基本遗传算法的构成要素

  基本遗传算法由染色体编码方法、适应度函数和遗传算子三个主要要素组成。下面将对每个要素进行详细说明:

1. 染色体编码

  染色体编码方法指将问题的解空间映射到染色体上的过程。通常采用二进制编码方法,将问题的解表示为一个二进制串。例如,在解决一个优化问题时,可以将每个解编码为一个二进制串,其中每一位代表一个决策变量的取值。除了二进制编码,还可以使用整数编码、浮点数编码或字符编码,根据问题的特性选择合适的编码方法。

2. 适应度函数

  适应度函数(又称适应值/适应函数)用于评价染色体的优劣程度,即衡量染色体对问题解的贡献或适应程度。适应度函数的设计应与问题的特性密切相关,通常通过问题的目标函数来定义。例如,在优化问题中,适应度函数可以直接使用目标函数的值作为染色体的适应度,或根据问题的约束条件进行适当的调整。

3. 遗传算子

  遗传算子是基本遗传算法的核心组成部分,包括选择算子、交叉算子和变异算子。

  • 选择算子(Selection):又称复制算子,按照某种策略从父代中挑选个体进入下一代,常见的选择算子包括比例选择、轮盘赌选择、锦标赛选择等。
    • 选择算子的目标是按染色体的适应度进行选择,以保留适应度较高的个体,促进种群的进化。
  • 交叉算子(Crossover):又称杂交算子,用于从选定的父代染色体中产生子代染色体。常见的交叉算子包括单点交叉、多点交叉等。
    • 交叉算子通过交换染色体的部分信息产生新的个体,增加种群的多样性。
  • 变异算子(Mutation):用于对染色体的个别基因进行随机变化。
    • 变异算子的作用是引入种群的随机性,避免陷入局部最优解。常见的变异算子包括单点变异、均匀变异等,通常具有较小的概率,以保持种群的稳定性

  基本遗传算法能够模拟自然进化的过程,通过选择、交叉和变异等遗传操作逐步优化种群,求得问题的最优解或近似解。

2.2 实验设计与方法

1. 算法流程

Created with Raphaël 2.3.0 开始 初始化群体 适应值评价,保存最优染色体 选择 交配 变异 重新评价适应值,更新最优染色体 满足终止条件? 结束 yes no

2. 伪代码

Procedure GeneticAlgorithm()
    t = 0 // 初始化迭代次数
    InitializePopulation(P(t)) // 初始化种群
    Evaluate(P(t)) // 评估种群中个体的适应度
    Best = KeepBest(P(t)) // 保留当前最优个体

    while (not TerminationConditionMet()) do
        P(t) = Selection(P(t)) // 选择操作
        P(t) = Crossover(P(t)) // 交叉操作
        P(t) = Mutation(P(t))  // 变异操作
        t = t + 1 // 更新迭代次数
        P(t) = P(t-1)
        Evaluate(P(t)) // 重新评估种群中个体的适应度
        if (BestIndividual(P(t)) > Best) then
            Best = ReplaceBest(P(t)) // 更新最优个体
        end if
    end while

    return Best // 返回找到的最优解
End Procedure

3. python实现

  本实验选择了一个简单的二次函数 m a x f ( x ) = x 2 , x ∈ [ 0 , 31 ] max f(x) = x^2, x \in [0, 31] maxf(x)=x2,x[0,31] 作为优化目标:

  • 对函数的解空间进行二进制编码
  • 随机生成初始种群
  • 计算每个个体的适应度使用选择、交叉和变异操作优化种群,直到达到设定的迭代次数。
  • 评估最优解的适应度并输出结果。
1. 导入模块
import random
2. 目标函数 f(x)
def f(x):
    return x ** 2
3 初始化种群
def initialize_population(population_size, chromosome_length):
    return [bin(random.randint(0, 31))[2:].zfill(chromosome_length) for _ in range(population_size)]

  生成指定大小的种群,每个个体都是一个长度为 chromosome_length (本实验为5)的二进制字符串,代表一个取值范围在 0 到 31 之间的整数。函数可以拆分为:

def initialize_population(size):
    return [encode(random.randint(0, 31)) for _ in range(size)]
  • 染色体编码函数 encode(x)
def encode(x):
    return bin(x)[2:].zfill(5)

  将整数 x 编码成一个长度为 5 的二进制字符串。内置的 bin() 函数将整数转换为二进制字符串,然后使用 zfill() 函数填充到长度为 5。

4. 计算适应度
def fitness(chromosome):
    return f(decode(chromosome))

这个函数计算染色体的适应度,即目标函数的取值。它通过先解码染色体,然后将解码后的值代入目标函数 f(x) 中来计算适应度。

5. 选择操作:轮盘赌选择
def selection(population, fitness_values):
    total_fitness = sum(fitness_values)
    # 计算每个个体被选中的概率
    probabilities = [fitness / total_fitness for fitness in fitness_values]
    # print("\t选择概率: {}".format(probabilities))
    selected_population = []
    for _ in range(len(population)):
        selected_individual = random.choices(population, weights=probabilities)[0]
        # print("\t被选个体: {}".format(selected_individual))
        selected_population.append(selected_individual)
    return selected_population

  从轮盘赌选择的机制中可以看到,较优染色体的P值较大,被选择的概率就相对较大。但由于选择过程具有随机性,并不能保证每次选择均选中这些较优的染色体,因此也给予了较差染色体一定的生存空间。

6. 单点交叉操作
def crossover(parent1, parent2):
    crossover_point = random.randint(1, len(parent1) - 1)
    child1 = parent1[:crossover_point] + parent2[crossover_point:]
    child2 = parent2[:crossover_point] + parent1[crossover_point:]
    print("\t\t交叉过程:{} ————> {}\n\t\t\t\t{} ————> {}".format(parent1, child1, parent2, child2))
    return child1, child2

  随机选择一个交叉点,然后将两个父代个体在交叉点处进行交换,生成两个新的子代个体。

7. 变异操作
def mutation(population, mutation_rate):
    mutated_population = []
    for individual in population:
        mutated_individual = ''
        for bit in individual:
            if random.random() < mutation_rate:
                mutated_bit = '0' if bit == '1' else '1'
            else:
                mutated_bit = bit
            mutated_individual += mutated_bit
        if mutated_individual != individual:
            print("\t\t变异过程:{} ————> {}".format(individual, mutated_individual))
        mutated_population.append(mutated_individual)
    return mutated_population

  对于染色体中的每个基因,根据指定的变异率,以一定概率对其进行变异(由 0 变为 1 或由 1 变为 0)。

8. 遗传算法
def genetic_algorithm(population_size, chromosome_length, crossover_rate, mutation_rate, max_iterations):
    population = initialize_population(population_size, chromosome_length)
    best_individual = None
    best_fitness = float('-inf')
    print(f"初始化群体:{population}")
    for iteration in range(max_iterations):
        print(f"第{iteration}代群体:{population}")
        # 评估种群中所有个体的适应度
        fitness_values = evaluate_population(population)
        print(f"\t 适应度: {fitness_values}")
        # 选择操作
        population = selection(population, fitness_values)
        print(f"\t选择操作:{population}")
        # 交叉操作
        for i in range(0, len(population), 2):
            if random.random() < crossover_rate:
                population[i], population[i + 1] = crossover(population[i], population[i + 1])
        print(f"\t交叉操作:{population}")

        # 变异操作
        population = mutation(population, mutation_rate)
        print(f"\t变异操作:{population}")

        # 更新最优个体
        max_fitness = max(fitness_values)
        if max_fitness > best_fitness:
            best_fitness = max_fitness
            best_individual = population[fitness_values.index(max_fitness)]

    return best_individual, best_fitness
    
9. 主程序
if __name__ == '__main__':
    # 设置参数
    population_size = 4  # 群体大小
    chromosome_length = 5  # 由于 x ∈ [0, 31],因此需要 5 位二进制编码
    crossover_rate = 0.9  # (提高)交叉率, 发生交叉的概率较大  𝑃_𝑐=0.8 , 0.9…
    # 哪两个个体配对交叉是随机的,交叉点位置的选取是随机的(单点交叉)
    mutation_rate = 0.01  # (降低)变异率, 变异概率𝑃_𝑚=0.01,0.05 … 交叉点位置的选取是随机的
    max_iterations = 2  # (增加)迭代次数

    # 运行遗传算法
    best_solution, max_fitness = genetic_algorithm(population_size, chromosome_length, crossover_rate, mutation_rate,
                                                   max_iterations)

    # 输出结果
    decoded_best_solution = int(best_solution, 2)
    print("最优解:", decoded_best_solution)
    print("最大适应度:", max_fitness)

在这里插入图片描述

2.3 实验结果与分析

  为了保持遗传算法较好的运行性能,变异概率P_c应该设置在一个合适的范围。变异操作通过改变原有染色体的基因,在提高群体多样性方面具有明显的促进作用如果P过小,算法容易早熟。但是在算法运行的过程中,已找到的较优解可能在变异过程中遭到破坏,如果P的值过大,可能会导致算法目前所处的较好的搜索状态倒退回原来较差的情况。因此,我们应该将种群的变异限制在一定范围内。一般地,P_c可设定在 0.001~0.1之间。

  实验结果显示,在给定的迭代次数内,遗传算法成功找到了函数 f ( x ) = x 2 f(x) = x^2 f(x)=x2 x ∈ [ 0 , 31 ] x \in [0, 31] x[0,31] 范围内的最大值。最终的最优解为 x = 31 x = 31 x=31,对应的最大适应度为 f ( 31 ) = 961 f(31) = 961 f(31)=961。通过动画展示了遗传算法的演化过程,直观地呈现了优化过程中种群的变化和适应度的提升。

2.4 结论与展望

  本文介绍了遗传算法的基本原理和实现过程,并通过实验展示了其在优化问题中的应用。实验结果表明,遗传算法能够有效地搜索解空间,并找到近似最优解。未来,可以进一步研究和优化遗传算法的参数设置、种群初始化和选择策略,以提高算法的性能和收敛速度。

3. 遗传算法的改进

4. 遗传算法的应用

5. 代码整合

import random


# 定义目标函数
def f(x):
    return x ** 2


# 初始化种群
def initialize_population(population_size, chromosome_length):
    return [bin(random.randint(0, 31))[2:].zfill(chromosome_length) for _ in range(population_size)]


# 计算个体的适应度
def evaluate_individual(individual):
    x = int(individual, 2)
    return f(x)


# 评估种群中所有个体的适应度
def evaluate_population(population):
    return [evaluate_individual(individual) for individual in population]


# 选择操作 - 轮盘赌选择算法
"""
从轮盘赌选择的机制中可以看到,较优染色体的P值较大,被选择的概率就相对较大。
但由于选择过程具有随机性,并不能保证每次选择均选中这些较优的染色体,因此也给予了较差染色体一定的生存空间。
"""


def selection(population, fitness_values):
    total_fitness = sum(fitness_values)
    # 计算每个个体被选中的概率
    probabilities = [fitness / total_fitness for fitness in fitness_values]
    # print("\t选择概率: {}".format(probabilities))
    selected_population = []
    for _ in range(len(population)):
        selected_individual = random.choices(population, weights=probabilities)[0]
        # print("\t被选个体: {}".format(selected_individual))
        selected_population.append(selected_individual)
    return selected_population


# 单点交叉操作
def crossover(parent1, parent2):
    crossover_point = random.randint(1, len(parent1) - 1)
    child1 = parent1[:crossover_point] + parent2[crossover_point:]
    child2 = parent2[:crossover_point] + parent1[crossover_point:]
    print("\t\t交叉过程:{} ————> {}\n\t\t\t\t{} ————> {}".format(parent1, child1, parent2, child2))
    return child1, child2


def mutation(population, mutation_rate):
    mutated_population = []
    for individual in population:
        mutated_individual = ''
        for bit in individual:
            if random.random() < mutation_rate:
                mutated_bit = '0' if bit == '1' else '1'
            else:
                mutated_bit = bit
            mutated_individual += mutated_bit
        if mutated_individual != individual:
            print("\t\t变异过程:{} ————> {}".format(individual, mutated_individual))
        mutated_population.append(mutated_individual)
    return mutated_population


# 主程序
def genetic_algorithm(population_size, chromosome_length, crossover_rate, mutation_rate, max_iterations):
    population = initialize_population(population_size, chromosome_length)
    best_individual = None
    best_fitness = float('-inf')
    print(f"初始化群体:{population}")
    for iteration in range(max_iterations):
        print(f"第{iteration}代群体:{population}")
        # 评估种群中所有个体的适应度
        fitness_values = evaluate_population(population)
        print(f"\t 适应度: {fitness_values}")
        # 选择操作
        population = selection(population, fitness_values)
        print(f"\t选择操作:{population}")
        # 交叉操作
        for i in range(0, len(population), 2):
            if random.random() < crossover_rate:
                population[i], population[i + 1] = crossover(population[i], population[i + 1])
        print(f"\t交叉操作:{population}")

        # 变异操作
        population = mutation(population, mutation_rate)
        print(f"\t变异操作:{population}")

        # 更新最优个体
        max_fitness = max(fitness_values)
        if max_fitness > best_fitness:
            best_fitness = max_fitness
            best_individual = population[fitness_values.index(max_fitness)]

    return best_individual, best_fitness


if __name__ == '__main__':
    # 设置参数
    """
    为了保持遗传算法较好的运行性能,变异概率P_c应该设置在一个合适的范围。
    变异操作通过改变原有染色体的基因,在提高群体多样性方面具有明显的促进作用如果P过小,算法容易早熟。
    但是在算法运行的过程中,已找到的较优解可能在变异过程中遭到破坏,如果P的值过大,可能会导致算法目前所处的较好的搜索状态倒退回原来较差的情况。
    因此,我们应该将种群的变异限制在一定范围内。一般地,P_c可设定在 0.001~0.1之间。
    """
    population_size = 4  # 群体大小
    chromosome_length = 5  # 由于 x ∈ [0, 31],因此需要 5 位二进制编码
    crossover_rate = 0.9  # (提高)交叉率, 发生交叉的概率较大  𝑃_𝑐=0.8 , 0.9…
    # 哪两个个体配对交叉是随机的,交叉点位置的选取是随机的(单点交叉)
    mutation_rate = 0.01  # (降低)变异率, 变异概率𝑃_𝑚=0.01,0.05 … 交叉点位置的选取是随机的
    max_iterations = 2  # (增加)迭代次数

    # 运行遗传算法
    best_solution, max_fitness = genetic_algorithm(population_size, chromosome_length, crossover_rate, mutation_rate,
                                                   max_iterations)

    # 输出结果
    decoded_best_solution = int(best_solution, 2)
    print("最优解:", decoded_best_solution)
    print("最大适应度:", max_fitness)

6. 随笔

  遗传算法作为一种启发式优化算法,在解决复杂问题和搜索空间较大的问题时表现出色。本文介绍了遗传算法的基本原理和应用,并通过实验展示了其在优化问题中的效果。希望本文能够对读者理解和应用遗传算法有所帮助。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20232906 2023-2024-2 《网络与系统攻防技术》第七次作业

20232906 2023-2024-2 《网络与系统攻防技术》第七次作业 1.实验内容 一、使用Metasploit进行Linux远程渗透攻击 任务&#xff1a;使用Metasploit渗透测试软件&#xff0c;攻击Linux靶机上的Samba服务Usermap_script安全漏洞&#xff0c;获取目标Linux靶机的主机访问权限。实…

如何在Spring Boot中配置数据库密码加密

如何在Spring Boot中配置数据库密码加密&#xff1f; alibaba/druid Wiki GitHub 使用ConfigFilter alibaba/druid Wiki GitHub 巧用Druid数据源实现数据库连接密码的加密解密功能 import com.alibaba.druid.filter.config.ConfigTools;public class Testttt {public stat…

汽车CAN总线技术详解

1. 历史 2. 应用 3. 优点 4. 基础概念 5. 组成 6. 应用 7. 网关 8. 波形分析 参考文献 汽车CAN总线技术详解&#xff08;100多页支持下载&#xff09;

帮助 Python 用户构建 CLI 界面:直观易写、简单高效 | 开源日报 No.240

tiangolo/typer Stars: 13.7k License: MIT typer 是一个构建出色命令行界面&#xff08;CLI&#xff09;的库&#xff0c;基于 Python 类型提示。它旨在让开发者轻松创建用户喜欢使用的 CLI 应用程序。其主要功能和核心优势包括&#xff1a; 直观易写&#xff1a;强大编辑器…

MySQL中怎么存放一条记录

2.2.1. MySQL中一行记录是怎么存储的&#xff1f; MySQL的数据存储在那个文件&#xff1f; 每创建一个 database&#xff08;数据库&#xff09;都会在 /var/lib/mysql/ 目录里面创建一个以 database 为名的目录&#xff0c;然后保存表结构和表数据的文件都会存放在这个目录里…

透视天气:数据可视化的新视角

数据可视化在天气方面能够为我们带来极大的帮助。天气是人类生活中一个重要的因素&#xff0c;对于农业、交通、航空、能源等各个领域都有着重要的影响。而数据可视化技术通过将复杂的天气数据转化为直观、易懂的图表、图像或地图等形式&#xff0c;为我们提供了更深入、更全面…

Windows系统下安装Mosquitto的步骤(2)

接前一篇文章&#xff1a;Windows系统下安装Mosquitto的步骤&#xff08;1&#xff09; 本文内容参考&#xff1a; Windows10上安装Mosquitto的步骤(win10、win11 安装mqtt) - IPS99技术分享 MQTT&#xff1a;windows环境下配置MQTT服务器&#xff08;mosquitto&#xff09;_…

第7篇:创建Nios II工程之控制LED<二>

Q&#xff1a;上一期我们完成了Quartus硬件工程部分&#xff0c;本期我们创建Nios II软件工程这部分。 A&#xff1a;创建完BSP和Nios II Application之后&#xff0c;在source文件main.c中添加LED控制代码&#xff1a;system.h头文件包含了Platform Designer系统中IP的硬件信…

复旦 北大 | 从头训练中文大模型:CT-LLM

引言 当前&#xff0c;绝大多数大模型&#xff08;LLMs&#xff09;基本上都是以英文语料库训练得到的&#xff0c;然后经过SFT来匹配不同的语种。然而&#xff0c;今天给大家分享的这篇文章旨在从头开始训练中文大模型&#xff0c;在训练过程中「主要纳入中文文本数据」&…

易查分如何使用导出PDF功能?

易查分的导出PDF文件功能可以将查询结果下载到本地&#xff0c;也可用于打印出纸质资料。老师和学生家长都可以自主导出PDF文件&#xff0c;下面就来教大家如何使用此功能。 &#x1f4cc;老师如何导出PDF&#xff1f; 在查询管理页&#xff0c;点击管理按钮-导出&#xff0c;可…

完美解决AttributeError: module ‘backend_interagg‘ has no attribute ‘FigureCanvas‘

遇到这种错误通常是因为matplotlib的后端配置问题。在某些环境中&#xff0c;尤其是在某些特定的IDE或Jupyter Notebook环境中&#xff0c;可能会因为后端配置不正确而导致错误。错误信息提示 module backend_interagg has no attribute FigureCanvas 意味着当前matplotlib的后…

经典网络解读——Efficientnet

论文&#xff1a;EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks&#xff08;2019.5&#xff09; 作者&#xff1a;Mingxing Tan, Quoc V. Le 链接&#xff1a;https://arxiv.org/abs/1905.11946 代码&#xff1a;https://github.com/tensorflow/t…

自动控制原理学习--平衡小车的控制算法(一)

基于单片机STM32的两轮平衡小车&#xff0c;单片机的各种IO、定时器、通讯等等一大堆要理解、编程&#xff0c;但这些都是琐碎的文档知识&#xff0c;需要花时间看各个模块的接口文档进而编程&#xff0c;需要良好的编程逻辑思维&#xff0c;去获取相关的传感模块信息&#xff…

Instal IIS on Windows Server 2022 Datacenter

和以往版本一样&#xff0c;没有什么不同&#xff0c;So easy&#xff01; WinR - ServerManager.exe 打开服务器管理器&#xff0c;点击【添加角色和功能】&#xff0c;选择自己想要的角色和功能。 一、开始之前&#xff1a;帮助说明&#xff0c;点击【下一步】&#xff1b;…

鸿蒙原生应用元服务开发-Web加载本地页面

将本地页面文件放在应用的rawfile目录下&#xff0c;开发者可以在Web组件创建的时候指定默认加载的本地页面 &#xff0c;并且加载完成后可通过调用loadUrl()接口变更当前Web组件的页面。 在下面的示例中展示加载本地页面文件的方法&#xff1a; 将资源文件放置在应用的resou…

Matlab生成txt文件导入到Vivado仿真

Matlab处理数据并将其写入txt文件 %% Txt Generate pre_RS_datadec2bin(simDataIn,8); %将数据转化为8bit的二进制 fidfopen("F:\FPGA\Xilinx_vivado\project\dvbstestbench\dbvs\matlab\pre_RS_data.txt","wt"); for i1:n*nMessages %数据…

网盘—下载文件

本文主要讲解网盘文件操作的下载文件部分&#xff0c;具体步骤如下&#xff1a; 目录 1、实施步骤 2、代码实现 2.1、添加下载文件的协议 2.2、添加下载文件函数 2.3、添加信号槽 2.4、实现槽函数 2.5、设置download状态 2.6、添加定义 2.7、服务器接收数据 2.8、添…

【docker】Docker开启远程访问

将构建的镜像自动上传到服务器。 需要开放 Docker 的端口&#xff0c;让我们在本地能连接上服务器的 Docker&#xff0c;这样&#xff0c;才能上传构建的镜像给 Docker。 开启远程访问 首先在服务器打开 Docker 的服务文件 vim /usr/lib/systemd/system/docker.service修改…

ubuntu下安装配置python3.11

方案1 添加仓库&#xff1a; $ sudo add-apt-repository ppa:deadsnakes/ppa $ sudo apt update $ sudo apt install python3.11然后查看有多少个python版本已经安装了&#xff1a; ls -l /usr/bin/python*python2.7,python 3.8 ,python 3.11. 然后&#xff0c;设置系统默认…

贪吃蛇小游戏(c语言)

1.效果展示 屏幕录制 2024-04-28 205129 2.基本功能 • 贪吃蛇地图绘制 • 蛇吃食物的功能 &#xff08;上、下、左、右方键控制蛇的动作&#xff09; • 蛇撞墙死亡 • 蛇撞自身死亡 • 计算得分 • 蛇身加速、减速 • 暂停游戏 3.技术要点 C语言函数、枚举、结构…