差分进化算法

一、简介

差分进化(DE)是一种算法,通过创建一些随机个体,将它们与预定义的评估指标进行比较,并保留最好的个体,然后通过混合剩余个体的特征来创建新的个体,并重复这个过程来解决全局优化问题。在接下来的编码中,向大家仔细地解释这个过程。

二、代码

# 创建一个对象。
from typing import List, Dict, Tuple, Union

class Individual:
    def __init__(
            self,
            parameters: Dict[str, float],
            score: Union[float, None] = None
    ) -> None:
        super().__init__()
        self.parameter_values = parameters
        self.score = score
   # 该对象保存单个个体的参数和分数。具有参数的个体x=2, y=3     
parameter_value = {"x":2, "y":3}
score = 13
# 评分
def scoring(ind: Individual) -> float:
    return ind.parameter_values["x"] ** 2 + ind.parameter_values["y"] ** 2
# 创造一个群体并进化它们。
class Population:
    # 最大化方向常量
    MAXIMIZE = 1
    # 最小化方向常量
    MINIMIZE = -1

    def __init__(
            self,
            pop_size,  # 种群大小
            direction: int,  # 优化方向(1 表示最大化,-1 表示最小化)
            bounds: Dict[str, Tuple[float, float]],  # 参数的边界范围字典
            parameters: List[str]  # 参数名称列表
    ) -> None:
        """
        初始化 Population 类的实例

        参数:
        pop_size (int):种群的大小
        direction (int):优化的方向,1 表示最大化,-1 表示最小化
        bounds (Dict[str, Tuple[float, float]]):包含每个参数的边界范围的字典
        parameters (List[str]):参数的名称列表
        """
        self.pop_size = pop_size
        self.direction = direction
        self.bounds = bounds
        self.parameters = parameters
        self.individuals: List[Individual] = []  # 存储个体的列表

    def _create_individual(self) -> Individual:
        """
        内部方法,用于创建一个个体

        返回:
        Individual:创建的个体
        """
        dict_parameters = {}  # 用于存储个体的参数值
        for parameter in self.parameters:
            # 在参数的边界范围内生成随机值
            param_value = random.uniform(self.bounds[parameter][0], self.bounds[parameter][1])
            dict_parameters[parameter] = param_value
        individual = Individual(parameters=dict_parameters)  # 创建个体对象
        individual.score = scoring(individual)  # 计算个体的得分
        return individual

    def initiate(self):
        """
        初始化种群,创建指定数量的个体并添加到 individuals 列表中
        """
        for i in range(self.pop_size):
            individual = self._create_individual()
            self.individuals.append(individual)

    def get_best_individual(self) -> Individual:
        """
        获取种群中得分最优的个体

        返回:
        Individual:得分最优的个体
        """
        self.best_individual = max(self.individuals, key=lambda x: x.score * self.direction)
        return self.best_individual

    def get_worst_individual(self) -> Individual:
        """
        获取种群中得分最差的个体

        返回:
        Individual:得分最差的个体
        """
        self.best_individual = min(self.individuals, key=lambda x: x.score * self.direction)
        return self.best_individual

    def get_mean_score(self) -> float:
        """
        计算种群中个体得分的平均值

        返回:
        float:个体得分的平均值
        """
        self.mean_score = sum([ind.score for ind in self.individuals]) / len(self.individuals)
        return self.mean_score

    def get_std_score(self) -> float:
        """
        计算种群中个体得分的标准差

        返回:
        float:个体得分的标准差
        """
        self.std_score = sum([(ind.score - self.mean_score) ** 2 for ind in self.individuals]) / len(self.individuals)
        return self.std_score
        class Optimization:
    def __init__(self, f: float, cp: float, population: Population):
        """
        初始化 Optimization 类的实例

        参数:
        f (float):某个相关的浮点数参数
        cp (float):某个相关的浮点数参数
        population (Population):种群对象
        """
        self.f = f
        self.cp = cp
        self.population = population

    @staticmethod
    def _mutant_choose(population: Population) -> Tuple[Individual, Individual, Individual]:
        """
        静态方法,从种群中选择 3 个随机个体

        参数:
        population (Population):要选择个体的种群

        返回:
        Tuple[Individual, Individual, Individual]:随机选择的 3 个个体
        """
        # 从种群的个体列表中随机抽取 3 个个体
        individuals = population.individuals
        random_individuals = random.sample(individuals, 3)
        return tuple(random_individuals)

    @staticmethod
    def _handle_boundaries(parameter_value: float, bounds: Tuple[float, float]) -> float:
        """
        静态方法,处理参数值超出边界的情况

        参数:
        parameter_value (float):要检查的参数值
        bounds (Tuple[float, float]):参数的边界范围

        返回:
        float:处理后的参数值
        """
        # 如果参数值大于上界,将其设为上界
        if parameter_value > bounds[1]:
            parameter_value = bounds[1]
        # 如果参数值小于下界,将其设为下界
        elif parameter_value < bounds[0]:
            parameter_value = bounds[0]
        return parameter_value

    @staticmethod
    def _calculate_parameter(
            semi_parents: Tuple[Individual, Individual, Individual],
            parameter_name: str,
            bounds: Tuple[float, float],
            f: float
    ) -> float:
        """
        静态方法,根据半亲代计算试验个体的参数

        参数:
        semi_parents (Tuple[Individual, Individual, Individual]):三个半亲代个体
        parameter_name (str):参数的名称
        bounds (Tuple[float, float]):参数的边界范围
        f (float):某个相关的浮点数参数

        返回:
        float:计算得到的试验个体的参数值
        """
        # 根据半亲代计算试验个体的参数
        trial_parameter = semi_parents[0].parameter_values[parameter_name] + \
                          f * (semi_parents[1].parameter_values[parameter_name] -
                               semi_parents[2].parameter_values[parameter_name])
        # 处理参数值超出边界的情况
        trial_parameter = Optimization._handle_boundaries(trial_parameter, bounds)
        return trial_parameter

    def _mutation(self, population: Population) -> Individual:
        """
        执行变异操作,创建试验个体

        参数:
        population (Population):要操作的种群

        返回:
        Individual:创建的试验个体
        """
        # 选择半亲代
        semi_parents = Optimization._mutant_choose(population)
        trial_parameters = {}
        # 对于每个参数名称
        for parameter in population.parameters:
            # 计算试验个体的参数
            trial_parameter = self._calculate_parameter(
                semi_parents, parameter,
                population.bounds[parameter],
                self.f
            )
            trial_parameters[parameter] = trial_parameter
        # 创建试验个体
        trial_individual = Individual(parameters=trial_parameters)
        return trial_individual

def _crossover(self, parent: Individual, trial: Individual, parameters):
    """
    执行交叉操作,生成子代个体

    参数:
    parent (Individual):父代个体
    trial (Individual):试验个体
    parameters (List[str]):参数列表

    返回:
    Individual:生成的子代个体
    """
    child_parameters = {}
    # 对于每个参数
    for parameter in parameters:
        # 生成随机概率
        prob = random.random()
        # 根据概率决定子代参数取值来自父代还是试验个体
        if prob < self.cp:
            child_parameters[parameter] = parent.parameter_values[parameter]
        else:
            child_parameters[parameter] = trial.parameter_values[parameter]
    # 创建子代个体
    child = Individual(parameters=child_parameters)
    return child

@staticmethod
def _selection(child: Individual, parent: Individual, direction: int) -> bool:
    """
    执行选择操作,比较子代和父代个体的得分,并根据方向决定是否选择子代

    参数:
    child (Individual):子代个体
    parent (Individual):父代个体
    direction (int):优化方向(1 表示最大化,-1 表示最小化)

    返回:
    bool:如果子代更优(或得分相等且倾向于选择子代),则返回 True,否则返回 False
    """
    child.score = scoring(child)
    # 在得分相等的情况下倾向于选择子代
    if direction == Population.MAXIMIZE:
        return child.score >= parent.score
    else:
        return child.score <= parent.score


def main(self, generations: int):
    """
    主函数,执行多代的优化过程

    参数:
    generations (int):要执行的代数
    """
    population = self.population

    for gen in range(generations):
        new_individuals = []

        for i in range(population.pop_size):
            # 变异操作
            trial_individual = self._mutation(population)

            # 交叉操作
            parent = population.individuals[i]
            child = self._crossover(parent, trial_individual, population.parameters)

            # 选择操作
            if self._selection(child, parent, self.population.direction):
                new_individuals.append(child)
            else:
                new_individuals.append(parent)

        # 用新的个体更新种群
        population.individuals = new_individuals

        # 在每一代结束时更新统计信息或执行其他必要任务
        best_individual = population.get_best_individual()
        worst_individual = population.get_worst_individual()
        mean_score = population.get_mean_score()
        std_score = population.get_std_score()

        # 打印或存储关于这一代的相关信息
        print(
            f"Generation {gen + 1}: Best Score - {best_individual.score}, Worst Score - {worst_individual.score}, Mean Score - {mean_score}, Std Score - {std_score}")

    # 完成所有代后,可以返回或执行任何最终操作
    final_best_individual = population.get_best_individual()
    print(
        f"Optimization complete. Best individual: {final_best_individual.parameter_values}, Score: {final_best_individual.score}")



population = Population(
    pop_size=50,
    direction=Population.MINIMIZE,
    bounds={"x": (-100, 100), "y": (-100, 100)},
    parameters=["x", "y"]
)
population.initiate()

optimization = Optimization(
    f=0.5,
    cp=0.7,
    population=population
)

optimization.main(20)

三、局限性

尽管差分进化算法用途广泛,但它也并非没有缺点。这些限制中最明显的是许多元启发式算法所面临的局部最优问题。DE算法或任何遗传算法都不能保证它们找到的最佳参数就是最佳解。想象一下一个深谷,我们的人口想要穿过它,人们想要降低地面,所以他们都可能会进入山谷并被困在那里,而其他地方有一个更深的山谷。更改参数以使其更加多样化,并围绕解决方案空间采取更大的步骤可以有所帮助,但会带来性能成本。

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

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

相关文章

分班结果老师怎么发给家长?

分班结果老师怎么发给家长&#xff1f; 随着新学期的脚步渐近&#xff0c;老师们的工作也变得愈发繁忙。从准备教学计划到整理课程材料&#xff0c;每一项任务都不容小觑。而其中&#xff0c;分班结果的告知工作&#xff0c;更是让不少老师头疼不已。传统的分班通知方式&#…

fork创建子进程详解

一.前言 在上一篇文章-进程的概念&#xff0c;最后我们提到了创建进程的方式有两种方式&#xff0c;一种是手动的创建出进程&#xff0c;还有一种就是我们今天要学习的使用代码的方式创建出子进程-fork。 而学习fork创建出进程的过程中&#xff0c;我们会遇到以下问题&#x…

STL——map和set

目录 一、set 二、map 1.插入 2.隆重介绍 [] A使用场景 B原理 一、set set即STL库中提供的K模型的二叉搜索树&#xff0c;他的函数使用和其他容器很相似&#xff0c;可以自行阅读文档#include <set> 本文旨对库中难以理解的函数作说明 二、map map即KV模型的二…

触底加载的两种思路(以vue3前端和nodejs后端为例)

一:首先,nodejs后端的代码都是一样的. 需要前端返回page参数,然后nodejs逻辑进行处理,截取页数和每页条数和总条数, 总条数用来作为判断是否有数据的条件,也可以不用,注意看下文 一:不用获取容器高度的. pinia中进行的axios请求处理 在vue文件中进行pinia中数据的导入,继续进…

全面解析 TypeScript 泛型的二三事

2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript 了。TypeScript 增强了代码可靠性和可维护性&#xff0c;确保减少运行时错误并提高开发人员的工作效率。 TypeScript 通过类型声明 使得 javascript 拥有了强类型校验。而泛型的是类型声明中最重要的一环&#x…

Nettyの源码分析

本篇为Netty系列的最后一篇&#xff0c;按照惯例会简单介绍一些Netty相关核心源码。 1、Netty启动源码分析 代码就使用最初的Netty服务器案例&#xff0c;在bind这一行打上断点&#xff0c;观察启动的全过程&#xff1a; 由于某些方法的调用链过深&#xff0c;节约篇幅&#xf…

Linux内核链表使用方法

简介&#xff1a; 链表是linux内核中最简单&#xff0c;同时也是应用最广泛的数据结构。内核中定义的是双向链表。 linux的链表不是将用户数据保存在链表节点中&#xff0c;而是将链表节点保存在用户数据中。linux的链表节点只有2个指针(pre和next)&#xff0c;这样的话&#x…

在Linux操作系统使用逻辑卷的快照(snapshot),进行对逻辑卷的数据备份。

作用&#xff1a;结合特定应用程序&#xff0c;方便备份数据。 基于cow&#xff08;copy on write 写时复制&#xff09;机制 在创建逻辑卷快照的时候&#xff0c;如果不去设置逻辑卷快照的权限的话&#xff0c;那么这个逻辑卷的权限就是可读可写&#xff0c; 创建逻辑卷快照…

coco数据集格式计算mAP的python脚本

目录 背景说明COCOeval 计算mAPtxt文件转换为coco json 格式自定义数据集标注 背景说明 在完成YOLOv5模型移植&#xff0c;运行在板端后&#xff0c;通常需要衡量板端运行的mAP。 一般需要两个步骤 步骤一&#xff1a;在板端批量运行得到目标检测结果&#xff0c;可保存为yol…

AI教你如何系统的学习Python

Python学习计划 第一阶段&#xff1a;Python基础&#xff08;1-2个月&#xff09; 目标&#xff1a;掌握Python的基本语法、数据类型、控制结构、函数、模块和包等。 学习Python基本语法&#xff1a;包括变量、数据类型&#xff08;整数、浮点数、字符串、列表、元组、字典、…

STM32基础篇:GPIO

GPIO简介 GPIO&#xff1a;即General Purpose Input/Output&#xff0c;通用目的输入/输出。就是一种片上外设&#xff08;内部模块&#xff09;。 对于STM32的芯片来说&#xff0c;周围有一圈引脚&#xff0c;有时需要对引脚进行读写&#xff08;读&#xff1a;从外部输入一…

【xinference】(15):在compshare上,使用docker-compose运行xinference和chatgpt-web项目,配置成功!!!

视频演示 【xinference】&#xff08;15&#xff09;&#xff1a;在compshare上&#xff0c;使用docker-compose运行xinference和chatgpt-web项目&#xff0c;配置成功&#xff01;&#xff01;&#xff01; 1&#xff0c;安装docker方法&#xff1a; #!/bin/shdistribution$(…

【嵌入式DIY实例-ESP8266篇】-LCD ST7735显示BMP280传感器数据

LCD ST7735显示BMP280传感器数据 文章目录 LCD ST7735显示BMP280传感器数据1、硬件准备与接线2、代码实现本文介绍如何将 ESP8266 NodeMCU 板 (ESP-12E) 与 Bosch Sensortec 的 BMP280 气压和温度传感器连接。 NodeMCU 微控制器 (ESP8266EX) 从 BMP280 传感器读取温度和压力值,…

VUE3初学入门-02-VUE创建项目

创建VUE项目的另一个方法 三种方法通过vue-cli进行创建通过npm进行创建比较 部署到nginx修改配置生成部署文件 三种方法 上一篇是在VSCODE中建立工作区&#xff0c;然后创建&#xff0c;属于命令加鼠标方式。个人感觉&#xff0c;在VSCODE基本上都是这样的操作&#xff0c;不是…

vue3中svg图标的封装与使用

组件封装&#xff1a; <template><svg :class"svgClass" :style"{ width: size px, height: size px, color: color, verticalAlign:deviationem}" aria-hidden"true"><use :xlink:href"#icon-${name}" /></s…

Python编程学习笔记(2)--- 列表简介

1、列表是什么 列表由一系列按特定顺序排列的元素组成。可以创建包含字母表中所有字母、数字、0~9或所有家庭成员姓名的列表&#xff1b;也可以将任何东西加入列表中&#xff0c;其中的元素之间可以没有任何关系。列表通常包含多个元素&#xff0c;因此给列表指定一个表示复数…

基于SSM+JSP的KTV点歌系统(带1w+文档)

基于SSMJSP的KTV点歌系统(带1w文档) 开发一个KTV点歌系统可以解决不利于线下点歌的问题&#xff0c;同时管理员可以利用网络对KTV点歌系统信息进行管理&#xff0c;设计的网站保证信息的完整安全&#xff0c;这样才能提高工作效率&#xff0c;保证系统安全正常的运行。 项目简介…

vim未找到命令,且yum install vim安装vim失败

vim未找到命令&#xff0c;且yum安装vim失败 1、wget更新yum云资源&#xff0c;本次更新为华为云镜像资源 wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.huaweicloud.com/repository/conf/CentOS-7-anon.repowget报未找到命令&#xff0c;请查看文章Linux wget…

iOS UITableView自带滑动手势和父视图添加滑动手势冲突响应机制探索

场景 我们有时候会遇到这样的一个交互场景&#xff1a;我们有一个UITableView 放在一个弹窗中&#xff0c;这个弹窗可以通过滑动进行展示和消失&#xff08;跟手滑动的方式&#xff09;&#xff0c;然后这个UITableView放在弹窗中&#xff0c;并且可以滚动&#xff0c;展示一些…

昇思25天学习打卡营第19天|Diffusion扩散模型

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) Diffusion扩散模型 本文基于Hugging Face&#xff1a;The Annotated Diffusion Model一文翻译迁移而来&#xff0c;同时参考了由浅入深了解Diffusion Model一文。 本教程在Jupyter Notebook上成…