简单遗传算法优化简单一元函数(python)

简介: 简单遗传算法优化简单一元函数(python)

👉待优化函数

本文待优化函数选取自《MATLAB智能算法30个案例分析(第2版)》中的第一个案例

利用遗传算法计算以下函数的最小值:

image.png

👉遗传算法流程

关于遗传算法的原理,书籍和文章均比较多,这里就不再赘述,这里给出简单遗传算法的流程

👉编码

这里着重说明一下编码方式,本文算法采用二进制编码。假设某一参数的取值范围是 [ U m i n , U m a x ] [U_{min},U_{max}][UminUmax],我们用长度为l ll的二进制编码符号串来表示该参数,则它总共能够产生2 l 2^l2l种不同的编码,若使参数编码时的对应关系如下:

则二进制编码的编码精度为: image.png

假设某一个体的编码是: image.png

则对应的解码公式为:

image.png

image.png 正是二进制对应的十进制数。

👉程序及运行结果

关于遗传算法各阶段运算,包括选择(复制)运算、交叉运算、变异运算均有不同的实现,本文代码参考了《遗传算法原理及应用》附录中C语言实现的简单遗传算法,有兴趣的读者可以对以上各阶段运算尝试其他的实现方式。

代码如下:

import math
import random
import copy
import matplotlib.pyplot as plt
PI = 3.1415926
# 个体长度
CHROM_LEN = 20
# 种群大小
POP_SIZE = 40
CMIN = 0
# 最大遗传代数
MAX_GENERATION = 40
# 交叉概率
PC = 0.7
# 变异概率
PM = 0.01
# 优化函数
def F(x):
    return math.sin(10 * PI * x) / x
# 解码器
def decode(chrom, lb, ub):
    # 二进制对应的十进制数
    temp = int(chrom, 2)
    # 最终解码值
    x = lb + temp * (ub - lb) / (math.pow(2, CHROM_LEN) - 1)
    return x
# 个体类
class Individual:
    def __init__(self):
        temp = []
        for _ in range(CHROM_LEN):
            temp.append(random.randint(0, 1))
        self.chrom = "".join([str(t) for t in temp])
        self.fitness = 0
    # 计算个体适应度
    def get_fitness(self, lb, ub):
        x = decode(self.chrom, lb, ub)
        value = -F(x) + CMIN
        self.fitness = max(0, value)
        return self.fitness
    def __str__(self):
        return "chrom:{}, fitness:{}".format(self.chrom, self.fitness)
# 获得当代最佳和最差个体索引
def best_and_worst(population):
    # 最佳个体索引
    best_idx = 0
    # 最差个体索引
    worst_idx = 0
    for _idx, p in enumerate(population):
        if p.fitness > population[best_idx].fitness:
            best_idx = _idx
        elif p.fitness < population[worst_idx].fitness:
            worst_idx = _idx
    return best_idx, worst_idx
# 选择(复制)操作
def select(population):
    # 新种群
    new_pop = []
    # 当代个体适应度总和
    fitness_sum = max(sum([i.fitness for i in population]), 0.0001)
    # 当代个体累计适应度占比
    cfitness = []
    # 计算相对适应度占比
    for j in range(POP_SIZE):
        cfitness.append(population[j].fitness / fitness_sum)
    # 计算累计适应度占比
    for j in range(POP_SIZE):
        if j == 0:
            continue
        cfitness[j] = cfitness[j-1] + cfitness[j]
    # 依据累计适应度占比进行选择复制,随机数大于对应的累计适应度占比,则进行复制
    for k in range(POP_SIZE):
        index = 0
        while random.random() > cfitness[index]:
            index += 1
            # 若无法找到要复制的其他个体,则沿用当前个体
            if index >= POP_SIZE:
                index = k
                break
        new_pop.append(copy.deepcopy(population[index]))
    return new_pop
# 交叉操作
def crossover(population):
    # 随机产生个体配对索引,类似于洗牌的效果
    index = [i for i in range(POP_SIZE)]
    for i in range(POP_SIZE):
        point = random.randint(0, POP_SIZE - i - 1)
        temp = index[i]
        index[i] = index[point + i]
        index[point + i] = temp
    for i in range(0, POP_SIZE, 2):
        if random.random() > PC:
            # 随机选择交叉开始位置
            cross_start = random.randint(0, CHROM_LEN - 2) + 1
            # 需要交换的基因
            cross_gene1 = population[index[i]].chrom[cross_start:]
            cross_gene2 = population[index[i + 1]].chrom[cross_start:]
            # 交叉操作
            population[index[i]].chrom = population[index[i]].chrom[0: cross_start] + cross_gene2
            population[index[i + 1]].chrom = population[index[i + 1]].chrom[0: cross_start] + cross_gene1
# 变异操作
def mutation(population):
    for individual in population:
        # 初始化新染色体
        new_chrom_ch = [c for c in individual.chrom]
        for i in range(CHROM_LEN):
            # 随机数小于变异概率,则进行变异操作
            if random.random() < PM:
                new_chrom_ch[i] = "1" if individual.chrom[i] is "0" else "0"
        # 更新染色体
        individual.chrom = "".join(new_chrom_ch)
# 绘制结果
def draw_result(best):
    import numpy as np
    # 绘制优化函数
    x = np.linspace(1, 2, 100)
    y = [F(_x) for _x in x]
    plt.plot(x, y)
    # 绘制最优解
    best_x = decode(best.chrom, 1, 2)
    best_y = F(decode(best.chrom, 1, 2))
    plt.scatter(best_x, best_y, s=100, c='red', marker='*', zorder=2)
    plt.show()
    # plt.savefig('sga_result.png', dpi=800)
# 绘制进化过程
def draw_evolution(evolution):
    x = [i for i in range(len(evolution))]
    plt.plot(x, evolution)
    plt.show()
    # plt.savefig('sga_evolution.png', dpi=800)
def main():
    # 种群
    population = []
    # 下界
    lb = 1
    # 上界
    ub = 2
    # 初始化种群
    for _ in range(POP_SIZE):
        population.append(Individual())
    # 计算初始种群适应度
    for individual in population:
        individual.get_fitness(lb, ub)
    # 初始种群最佳和最差个体
    best_idx, worst_idx = best_and_worst(population)
    # 历史最佳个体
    current_best = population[best_idx]
    # 进化过程,每一代的最佳个体的函数值
    evolution = []
    # 循环直到最大代数
    for generation in range(MAX_GENERATION):
        # 选择复制
        population = select(population)
        # 交叉
        crossover(population)
        # 变异
        mutation(population)
        # 重新计算适应度
        for individual in population:
            individual.get_fitness(lb, ub)
        # 当代种群最佳和最差个体索引
        best_idx, worst_idx = best_and_worst(population)
        # 利用精英模型执行进化操作,用历史最佳个体代替当代的最差个体
        if population[best_idx].fitness > current_best.fitness:
            current_best = population[best_idx]
        else:
            population[worst_idx] = current_best
        # 更新进化过程
        evolution.append(round(F(decode(current_best.chrom, 1, 2)), 4))
    # 绘制进化过程
    # draw_evolution(evolution)
    # 绘制结果
    draw_result(current_best)
    # 打印最佳结果
    print("X = {}".format(round(decode(current_best.chrom, 1, 2), 4)))
    print("Y = {}".format(round(F(decode(current_best.chrom, 1, 2)), 4)))
if __name__ == "__main__":
    main()

代码输出最优解为:

X = 1.1491
Y = -0.8699

待优化函数及最优解如下图所示:

每一代最优解的进化过程如下图所示(由于初始种群的随机性,每一次执行产生的结果可能会不同):

搜索最优解的动态图如下图所示(由于初始种群的随机性,每一次执行产生的结果可能会不同):

👉问题

由于初始种群的随机性,每一次得到的最优解可能会稍有差异,本文代码有时会找不到全局最优解,稳定性有待提升,在此作者抛砖引玉,希望有实力的读者能进一步优化并留言

笔者水平有限,若有不对的地方欢迎评论指正

相关文章
|
9天前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能食品加工优化的深度学习模型
使用Python实现智能食品加工优化的深度学习模型
104 59
|
11天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
|
6天前
|
机器学习/深度学习 算法 数据可视化
使用Python实现深度学习模型:智能食品配送优化
使用Python实现深度学习模型:智能食品配送优化
21 2
|
5天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
25 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
5天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
21 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
5天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
25 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
9天前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
26 2
|
10天前
|
搜索推荐 Python
快速排序的 Python 实践:从原理到优化,打造你的排序利器!
本文介绍了 Python 中的快速排序算法,从基本原理、实现代码到优化方法进行了详细探讨。快速排序采用分治策略,通过选择基准元素将数组分为两部分,递归排序。文章还对比了快速排序与冒泡排序的性能,展示了优化前后快速排序的差异。通过这些分析,帮助读者理解快速排序的优势及优化的重要性,从而在实际应用中选择合适的排序算法和优化策略,提升程序性能。
23 1
|
11天前
|
人工智能 算法 大数据
Linux内核中的调度算法演变:从O(1)到CFS的优化之旅###
本文深入探讨了Linux操作系统内核中进程调度算法的发展历程,聚焦于O(1)调度器向完全公平调度器(CFS)的转变。不同于传统摘要对研究背景、方法、结果和结论的概述,本文创新性地采用“技术演进时间线”的形式,简明扼要地勾勒出这一转变背后的关键技术里程碑,旨在为读者提供一个清晰的历史脉络,引领其深入了解Linux调度机制的革新之路。 ###
|
14天前
|
运维 监控 Linux
自动化运维:如何利用Python脚本优化日常任务##
【10月更文挑战第29天】在现代IT运维中,自动化已成为提升效率、减少人为错误的关键技术。本文将介绍如何通过Python脚本来简化和自动化日常的运维任务,从而让运维人员能够专注于更高层次的工作。从备份管理到系统监控,再到日志分析,我们将一步步展示如何编写实用的Python脚本来处理这些任务。 ##