【机器学习】【遗传算法】【项目实战】药品分拣的优化策略【附Python源码】

仅供学习、参考使用

一、遗传算法简介

遗传算法(Genetic Algorithm, GA)是机器学习领域中常见的一类算法,其基本思想可以用下述流程图简要表示:

(图参考论文:Optimization of Worker Scheduling at Logistics
Depots Using GeneticAlgorithms and Simulated
Annealing)

在这里插入图片描述

一种常见的遗传算法变例是有偏随机密匙遗传算法 (BRKGA: Biased Random Key Genetic Algorithm) ,参考论文:A BIASED RANDOM-KEY GENETIC ALGORITHM WITH VARIABLE MUTANTS TO
SOLVE A VEHICLE ROUTING PROBLEM,算法流程大致如下:
(图参考博客:Pymoo学习 (11):有偏随机密匙遗传算法 (BRKGA: Biased Random Key Genetic Algorithm) 的使用)

在这里插入图片描述

二、项目源码(待进一步完善)

1、导入相关库

import csv
import random
import numpy as np
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt

2、药品统计

# 统计zone_id=2110的药品
def screen_goods_id(tote_data, zone):
    zone_goods_id_lists = []
    for i in range(len(tote_data)):
        zone_id = tote_data['区段ID'][i]
        goods_id = tote_data['产品编号'][i]
        if zone_id == zone:
            zone_goods_id_lists.append(goods_id)
    zone_goods_id_lists = list(set(zone_goods_id_lists))
    return zone_goods_id_lists

3、货位统计

# 统计zone_id=2110的货位
def generate_locations():
    index_id_0 = [2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181]
    index_id_1 = [1, 2, 3, 4, 5, 6, 7, 8]
    index_id_2 = [21, 22, 23, 24, 25, 31, 32, 33, 34, 35, 41, 42, 43, 44, 45]
    location_id_data = [f"{aa:04d}{bb:02d}{cc:02d}1" for aa in index_id_0 for bb in index_id_1 for cc in index_id_2]
    return location_id_data

4、缺失货位统计

# 统计zone_id=2110的缺失货位
def del_locations():
    index_id_0 = [217408, 217507, 217708, 217807, 218008, 218107]
    index_id_1 = [22, 23, 24, 25, 32, 33, 34, 35, 42, 43, 44, 45]
    del_loc_data = [f"{aa:06d}{bb:02d}1" for aa in index_id_0 for bb in index_id_1]
    return del_loc_data

5、生成可使用货位

# 去除缺失货位,生成最终的可使用货位
def screen_location_id():
    location_id_data = generate_locations()
    del_loc_data = del_locations()
    location_id_lists = [loc_id for loc_id in location_id_data if loc_id not in del_loc_data]
    return location_id_lists

6、个体(单个基因型)生成

# 生成一个个体
def pop_one_combined(list_1, list_2):  # list1的长度不能大于list2
    goods_ids_copy = list_1[:]
    location_ids_copy = list_2[:]
    combined_list = []
    for _ in range(len(list_1)):
        element = random.choice(location_ids_copy)
        location_ids_copy.remove(element)
        combined_list.append(element)
    return combined_list

生成测试:大小为6的一维数组,生成50个个体(种群类似):

list1 = [1, 2, 3, 4, 5, 6]
list2 = [1, 2, 3, 4, 5, 6]

# 个体生成测试(批量生成)

for i in range(50):
    print(pop_one_combined(list1, list2))

在这里插入图片描述
7、种群(基因池)生成

# 生成种群
def generate_pop_list(POP_SIZE, zone_goods_id_data, zone_location_id_data):
    pop_list = []
    for _ in range(POP_SIZE):
        pop_individuality = pop_one_combined(zone_goods_id_data, zone_location_id_data)
        pop_list.append(pop_individuality)
    return pop_list

生成测试:

# 种群生成测试(样本量50)
print(generate_pop_list(50, list1, list2))

在这里插入图片描述
8、劳累值(特征系数)计算公式

# 拣选劳累值计算公式
def pick_distance_formula(location_id, shelves_num):
    if location_id[-2] == '4':  # 第4层(最高层)
        distance = 10 * (int(location_id[0:4]) - 2173) + (shelves_num - 1) * 10 + int(location_id[-3]) + 3
    else:  # 第1~3层
        distance = 10 * (int(location_id[0:4]) - 2173) + (shelves_num - 1) * 10 + int(location_id[-3])
    return distance

9、一组数据的劳累值计算

# 拣选劳累值计算(一组)
def pick_distance_value(location_id):
    distance = 0
    shelves_num = int(location_id[4:6])
    group_1 = [1, 3, 5, 7]
    group_2 = [2, 4, 6, 8]
    if shelves_num in group_1:
        shelves_num = shelves_num // 2 + 1
    elif shelves_num in group_2:
        shelves_num = shelves_num // 2
    distance = pick_distance_formula(location_id, shelves_num)
    return distance

10、选择优势个体进入下一代

# 选择优胜个体
def select(pop_list, CROSS_RATE, POP_SIZE):
    index = int(CROSS_RATE * POP_SIZE)  # 一轮筛选后的样本数量
    return pop_list[0:index]  # 返回前xxx个优胜个体

11、遗传变异机制

# 遗传变异
def mutation(MUTA_RATE, child, zone_goods_id_data, zone_location_id_data):
    if np.random.rand() < MUTA_RATE:
        mutation_list = [loc_id for loc_id in zone_location_id_data if loc_id not in child]
        num = np.random.randint(1, int(len(zone_goods_id_data) * MUTA_RATE))
        for _ in range(num):
            index = np.random.randint(0, len(zone_goods_id_data))
            mutation_list.append(child[index])
            loc_id = random.choice(mutation_list)
            child[index] = loc_id
    return child

12、子代中0值的替换

# (子代)0值的替换
def obx_count_run(child, parent):
    for parent_elemental in parent:
        if parent_elemental not in child:
            for i in range(len(child)):
                if child[i] == 0:
                    child[i] = parent_elemental
                    break
    return child

13、基于顺序的交叉方式(Order-Based Crossover, OBX)

# 遗传交叉(交叉算子:基于顺序的交叉(Order-Based Crossover,OBX))
def crossmuta(pop_list, POP_SIZE, MUTA_RATE, zone_goods_id_data, zone_location_id_data):
    pop_new = []
    for i in range(len(pop_list)):
        pop_new.append(pop_list[i][1:])
    while len(pop_new) < POP_SIZE:
        parent_1 = random.choice(pop_list)[1:]
        parent_2 = random.choice(pop_list)[1:]
        while parent_1 == parent_2:
            parent_2 = random.choice(pop_list)[1:]
        child_1 = [0 for _ in range(len(zone_goods_id_data))]
        child_2 = [0 for _ in range(len(zone_goods_id_data))]
        for j in range(len(zone_goods_id_data)):
            genetic_whether = np.random.choice([0, 1])
            if genetic_whether == 1:
                child_1[j] = parent_1[j]
                child_2[j] = parent_2[j]
        if (child_1 == parent_1) or (child_2 == parent_2):
            continue
        child_1 = obx_count_run(child_1, parent_2)
        child_1 = mutation(MUTA_RATE, child_1, zone_goods_id_data, zone_location_id_data)
        child_2 = obx_count_run(child_2, parent_1)
        child_2 = mutation(MUTA_RATE, child_2, zone_goods_id_data, zone_location_id_data)
        pop_new.append(child_1)
        pop_new.append(child_2)
    return pop_new

14、损失曲线图绘制

# 每轮总拣选劳累值绘制曲线图
def loss_chart(data):
    y_values = data
    x_values = list(range(len(y_values)))
    plt.plot(x_values, y_values)
    plt.title("zone_2110_pick_distance_loss")
    plt.xlabel("Iterations")  # 迭代次数
    plt.ylabel("zone_2110_pick_distance")  # 距离
    plt.grid()
    plt.savefig('./JS_zone_2110_pick_distance_loss.png')
    plt.show()

15、结果合成

# 最终结果合成
def goods_location_data_consolidation(zone_goods_id_data, zone_goods_location_id_data):
    goods_location_data = []
    for i in range(len(zone_goods_id_data)):
        goods_location_data.append([zone_goods_id_data[i], zone_goods_location_id_data[i]])
    return goods_location_data

主函数及运行:

def main():
    list1 = [1, 2, 3, 4, 5, 6]
    list2 = [1, 2, 3, 4, 5, 6]

    # 个体生成测试(批量生成)

    for i in range(50):
        print(pop_one_combined(list1, list2))

    # 种群生成测试(样本量50)
    print(generate_pop_list(50, list1, list2))

    print("Genetic algorithm run start")
    print(f"start_time --> {datetime.now()}")
    zone_2110_pick_distance = []
    tote_goods_data_2403 = pd.read_csv('./tote_goods_data_2024_03.csv')  # 读取数据集
    POP_SIZE = 20  # 种群大小
    CROSS_RATE = 0.9  # 交叉率
    MUTA_RATE = 0.05  # 变异率
    Iterations = 10  # 迭代次数
    zone_2110_goods_id_lists = screen_goods_id(tote_goods_data_2403, 2110)
    zone_2110_location_id_lists = screen_location_id()
    POP = generate_pop_list(POP_SIZE, zone_2110_goods_id_lists, zone_2110_location_id_lists)
    for i in range(Iterations):
        POP = getfitness(POP, 2110, tote_goods_data_2403, zone_2110_goods_id_lists)
        POP = select(POP, CROSS_RATE, POP_SIZE)
        zone_2110_pick_distance.append(POP[0][0])
        POP = crossmuta(POP, POP_SIZE, MUTA_RATE, zone_2110_goods_id_lists, zone_2110_location_id_lists)
    loss_chart(zone_2110_pick_distance)

    Updated_goods_location_data = goods_location_data_consolidation(zone_2110_goods_id_lists, POP[0])
    with open('./zone_2110_goods_location_data.csv', 'w', newline='') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(['goods_id', 'location_id'])
        for row in Updated_goods_location_data:
            writer.writerow(row)

    print(f"end_time --> {datetime.now()}")
    print("Genetic algorithm run end")


if __name__ == "__main__":
    main()

三、算法测试

1、pop_size=20, iterations=10
cross_rate=0.5, muta_rate=0.05:
在这里插入图片描述
交叉率不变,增加变异率到0.1:

在这里插入图片描述

变异率不变,增加交叉率到0.9:

在这里插入图片描述

2、在另一个数据集上进行测试

采用初始参数设定:
在这里插入图片描述

交叉率提高至0.9:
在这里插入图片描述

四、算法优化(待更新)

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

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

相关文章

EMQX Enterprise 5.7 发布:新增会话持久化、消息 Schema 验证、规则引擎调试与追踪功能

EMQX Enterprise 5.7.0 版本现已正式发布&#xff01; 在这个版本中&#xff0c;我们引入了一系列新的功能和改进&#xff0c;包括会话持久化、消息 Schema 验证、规则引擎调试与追踪测试等功能。此外&#xff0c;新版本还进行了多项改进以及 BUG 修复&#xff0c;进一步提升了…

QT 编译Lua 动态库,使用Lua脚本混合编程

一,编译Lua动态库 1,下载lua源码 地址:Lua: downloadhttps://www.lua.org/download.html 2,配置 解压lua源码压缩包,里面有个src文件夹,里面的代码就是lua的源码

TMS320F280049 ECAP模块--capture模式(1)

功能框图 event预分频 如下图所示&#xff0c;可以对输入信号进行预分频。 一次性触发和连续触发 如下图所示&#xff0c;可以进行一次性触发&#xff0c;也可以进行连续触发。 中间计数器的clk是事件1-4&#xff0c;stop是由一次性触发逻辑控制&#xff0c;rst是由ctrfiltre…

【数据结构与算法 经典例题】(C语言)反转链表图文详解

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法 经典例题》C语言 期待您的关注 ​ 目录 一、问题描述 二、解题思路分析 三、代码实现 一、问题描述 二、解题…

华为机考入门python3--(33)牛客33-整数与IP地址间的转换

分类&#xff1a;进制转换 知识点&#xff1a; 十进制转8位二进制 format(num, 08b) 二进制转十进制 int(binary_str, 2) 列表中元素类型转换 new_list map(int, old_list) 题目来自【牛客】 # 将IP地址转换为十进制形式的整数 def ip_to_int(ip):# map返回的是迭…

SEO之关键词扩展(一)

初创企业搭建网站的朋友看1号文章&#xff1b;想学习云计算&#xff0c;怎么入门看2号文章谢谢支持&#xff1a; 1、我给不会敲代码又想搭建网站的人建议2、新手上云 确定了核心关键词后&#xff0c;接下来就是进行关键词扩展。对一个稍有规模的网站来说&#xff0c;研究几十个…

【计算机毕设】【计算机毕设】基于SpringBoot平台的医疗病历交互系统设计与实现 - 源码免费(私信领取) - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 本项目旨在设计并实现一个基于SpringBoot的医疗病历交互系统&#xff0c;以改善病历管理和医患沟通的效率&#xff0c;提升医疗服务质量。具体目标包…

质数计数问题求解

质数计数问题求解 题目 leetcdoe204 计数质数:https://leetcode.cn/problems/count-primes 给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。 示例1: 输入:n = 10 输出:4 解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 示例 2: 输入:n = 0 输出:0 示…

Go 线程同步

一、介绍 通常在 Go 语言中有两种方法可以用来做线程同步 sync.Cond channel channel 的很好理解&#xff0c;当我们从一个 channel 中接收数据的时候&#xff0c;如果里面没有数据&#xff0c;那我们直接就阻塞在那里了。 在 Go 语言中&#xff0c;如果你尝试在已经持有某…

【设计模式】JAVA Design Patterns——Monitor(监视器模式)

&#x1f50d;目的 主要目的是为多个线程或进程提供一种结构化和受控的方式来安全地访问和操作共享资源&#xff0c;例如变量、数据结构或代码的关键部分&#xff0c;而不会导致冲突或竞争条件。 &#x1f50d;解释 通俗描述 监视器模式用于强制对数据进行单线程访问。 一次只允…

基于java的CRM客户关系管理系统(六)

目录 5.3 表现层设计 5.3.1 模型层&#xff08;M&#xff09; 5.3.2 视图层&#xff08;V&#xff09; 5.3.3 控制层&#xff08;C&#xff09; 5.4 系统主要功能模块的实现 5.4.1 登录功能的实现 5.4.2 客户管理的实现 5.5 本章小结 参考文献 前面内容请移步 基于java…

基本元器件 - 电感与磁珠

电感 电感的选型 体积大小电感值所在工作频率开关频率下的电感值为实际需要的电感值线圈的直流阻抗&#xff08;DCR&#xff09;越小越好工作电流应降额至额定饱和电流的 0.7 倍以下&#xff0c;额定 rms 电流&#xff1b;交流阻抗&#xff08;ESR&#xff09;越小越好&#…

10 款在线剽窃检查的 [免费工具]

剽窃或抄袭他人文章而不注明出处&#xff0c;几乎在所有领域都被认为是有害的。然而&#xff0c;学术界最痛恨这种行为。抄袭是对学术诚信的最大威胁。这就是为什么每个教育机构总是希望学生提交无抄袭的作业。 然而&#xff0c;有时学生无意中剽窃了他人的作业&#xff0c;直…

【软件开发】Java学习路线

本路径视频教程均来自尚硅谷B站视频&#xff0c;Java学习课程我已经收藏在一个文件夹下&#xff0c;B站文件夹同时会收藏其他Java视频&#xff0c;感谢关注。指路&#xff1a;https://www.bilibili.com/medialist/detail/ml3113981545 2024Java学习路线&#xff08;快速版&…

命名空间,缺省参数和函数重载

前言&#xff1a;本文章主要介绍一些C中的小语法。 目录 命名空间 namespace的使用 访问全局变量 namespace可以嵌套 不同文件中定义的同名的命名空间可以合并进一个命名空间&#xff0c;并且其中不可以有同名的变量 C中的输入和输出 缺省参数&#xff08;默认参数&#…

超越Devin!姚班带队,他们创大模型编程新世界纪录

超越Devin&#xff01;SWEBench排行榜上迎来了新玩家—— StarShip CodeGen Agent&#xff0c;姚班带队初创公司OpenCSG出品&#xff0c;以23.67%的成绩获得全球第二名的成绩。 同时创造了非GPT-4o基模的最高纪录&#xff08;SOTA&#xff09;。 我们都知道&#xff0c;SWEBe…

for深入学习

目录 练习&#xff1a; 例1&#xff1a; 求解0-100中整除3的数有哪些 例2&#xff1a; 求0-100中含数字9个个数 作业&#xff1a; 练习&#xff1a; 例1&#xff1a; 求解0-100中整除3的数有哪些 代码&#xff1a; #include<stdio.h> int main() {printf("整…

JAVAEE之网络初识_协议、TCP/IP网络模型、封装、分用

前言 在这一节我们简单介绍一下网络的发展 一、通信网络基础 网络互连的目的是进行网络通信&#xff0c;也即是网络数据传输&#xff0c;更具体一点&#xff0c;是网络主机中的不同进程间&#xff0c;基于网络传输数据。那么&#xff0c;在组建的网络中&#xff0c;如何判断到…

深入理解计算机系统 第三版 中文版 图5-27 p371 错漏

中文版 英文版 对照 可以看出错漏 这本书中文版很多错漏,可以配合英文版查正,不过英文版也很多错漏,所以不用太相信书本.要根据自己的理解来.

TDengine为物联网而生的大数据平台

TDengine为物联网而生的大数据平台 物联网背景 技术支撑 应用落地 未来趋势