带模糊加工时间的柔性作业车间调度理论和GA复现(python)

news2024/10/6 0:27:02

文章目录

    • 1.模糊作业车间
      • 1.1 模糊数
      • 1.2 三角模糊数操作
      • 1.3 模糊甘特图
    • 2.FJSP+模糊加工时间+GA
      • 2.1 GA算法设置
      • 2.2 python代码
      • 2.3 测试结果

1.模糊作业车间

1.1 模糊数

论域X上的模糊集合A由隶属度函数u(x)表示,u(x)取值[0,1]。如果A为三角模糊数,A可以表示为(a1,aM,a2)。如果A为四角模糊数,A可以表示为(a1,a2,a4,a5)。各模糊数和隶属度函数如下所示:
在这里插入图片描述
在这里插入图片描述
对于不确定条件下的工件加工时间和完工时间,采用三角模糊数来进行描述。对于不确定条件下的交货期,采用梯形模糊数来进行描述。例如job1的第一个操作O11,其在机器1上的模糊加工时间用三角模糊数表示(4,7,12),三个数分别表示最好的,最可能的,最坏的加工时间。一个带有模糊加工时间的4job 和 2machine的柔性作业车间调度问题数据案例如下:括号为实际加工时间,可不考虑
在这里插入图片描述

1.2 三角模糊数操作

【1】Sakawa, M., & Mori, T. (1999). An efficient genetic algorithm for job-shop scheduling problems with fuzzy processing time and fuzzy duedate. Computers & Industrial Engineering, 36(2), 325-341. doi:https://doi.org/10.1016/S0360-8352(99)00135-7
【2】Sakawa, M., & Kubota, R. (2000). Fuzzy programming for multiobjective job shop scheduling with fuzzy processing time and fuzzy duedate through genetic algorithms. European Journal of Operational Research, 120(2), 393-407. doi:https://doi.org/10.1016/S0377-2217(99)00094-6

要求解车间调度问题,会遇到加工时间的一些计算,比如求加工开始时间,加工完成时间,和确定数操作一样,模糊数的操作也非常重要,主要包括模糊数的求和和取大操作以及对模糊数的比较。

  • 求和:计算每个操作的模糊完成时间[1]

在这里插入图片描述

  • 取大:计算每个操作的模糊开始时间[1]

在这里插入图片描述

  • 比较:模糊完成时间是模糊加工时间的总和,因此也变成了三角模糊数,如果要最小化最大的模糊完成时间,就要比较一些模糊完成时间的值[2]
    在这里插入图片描述
  • 举例

假设有2✖️2的JSP问题:
Job 1: Machine 1 (2, 5, 6), Machine 2 (5, 7, 8)
Job 2: Machine 2 (3, 4, 7), Machine 1 (1, 2, 3)
那么Job1的第二个操作模糊开始时间为(2, 5, 6)V(3, 4, 7),即(3, 5, 7);模糊完成时间为(3, 5, 7)+(5, 7, 8)=(8, 12, 15)
假设有4个三角模糊数为A1=(2,5,8),A2=(3,4,9),A3=(3,5,7),A4=(4,5,8),根据比较原则可得A4,A1,A3,A2

1.3 模糊甘特图

由于每个操作的开始时间和完成时间都是三角模糊数,因此其甘特图也与正常甘特图不同,如下图,每个操作的模糊开始时间在直线下面,模糊完成时间在直线上面,每个三角形就是前面提到的隶属度函数图像。如果是机器上第一个加工,用长方形表示。如O41模糊开始时间为(4,5,7),接下来要在M1上加工,而M1最快的模糊结束时间为O31的(6,10,14),因此O42模糊开始时间为(6,10,14)。
在这里插入图片描述
在这里插入图片描述

2.FJSP+模糊加工时间+GA

2.1 GA算法设置

复现文章:【3】Lei, D. M. (2010). A genetic algorithm for flexible job shop scheduling with fuzzy processing time. International Journal of Production Research, 48(10), 2995-3013. doi:10.1080/00207540902814348

与前面介绍不同,[3]提出了新的max操作算子,即直接根据rank结果确定,两个三角模糊数s,t中的较大值要么是s,要么是t
在这里插入图片描述

  • 编码和解码(two-string)

用两层编码表示,一层为操作序列,一层为选择机器,注意第二层的机器分配编码对应的是各个操作按顺序排下来的机器,与第一层编码无关。比如操作011最后加工,加工机器为1。
在这里插入图片描述
在部分其它文献中的两层编码,第二层的机器编码对应的是第一层编码下每个操作的加工机器,与此处不同。下面是另一种编码方式,比如操作023最后加工,加工机器为M5。
在这里插入图片描述
适应度值为目标函数值(模糊完成时间)

  • 选择(tournament select)

使用精英策略,即保留每代种群里最优的个体。由于模糊目标值,轮盘赌选择(roulette wheel)方式不适合,因此使用锦标赛选择(tournament select)。有放回的从种群中随机选择两个个体,选择适应度值较小的个体进入新种群

  • 交叉(TPX;GPX/GPPX)

将种群分成两个子种群A和B,分别代表作业序列和机器分配。对于机器分配部分,交叉使用两点交叉(two point crossover TPX)。对于作业序列部分,使用两种交叉:generalised position crossover (GPX)和generalisation of the precedence preservative crossover (GPPX)
GPX:从parent1中选择子字符串S,如S=1231,找到S中每个元素在parent2中的位置并删除对应的元素,注意元素是有顺序的,如S中的1在parent1中是第二次出现,因此要找到parent2中第二次出现的1,删除S后parent2变成32414234,将S插入到parent2中,位置等于S在parent1中的位置,即pos=4
在这里插入图片描述
GPPX:设置一个取值[1,2]的string,分表代表从parent1(2)中相继选择基因,如果从parent1中选择了一个基因,删除其在parent2对应的基因
在这里插入图片描述

  • 变异(swap)

对于某个个体,随机选择两个基因并交换

  • 算法

随机生成N个个体的初始种群P;
对P执行tournament select;
将P分成两个子种群A和B,分别代表作业序列和机器分配部分;
对种群A执行GPPX或者GPX交叉和swap变异;
对种群B执行TPX交叉和swap变异;
合并A和B生成新种群并计算适应度值;
迭代直到结束

2.2 python代码

操作序列用GPPX交叉算子,交叉率=0.8,变异率=0.1,种群数=100,迭代数=1000,编码第二种方式,下面是GA部分,完整代码https://github.com/bujibujibiuwang/solve-fuzzy-FJSP-with-GA

import random
from params import get_args
from Shop import Shop
from utils import *


class GA(object):
    def __init__(self, args, shop):
        self.shop = shop
        self.cross_rate = args.cross_rate
        self.mutate_rate = args.mutate_rate
        self.pop_size = args.pop_size
        self.elite_number = args.elite_number

        self.chrom_size = self.shop.job_nb * self.shop.op_nb
        self.pop = []

    def encode(self):
        init_pop = []
        for _ in range(self.pop_size):
            one_string = []
            for _ in range(self.shop.op_nb):
                one_string += list(np.random.permutation(self.shop.job_nb))
            random.shuffle(one_string)
            two_string = [random.randint(0, self.shop.machine_nb-1) for _ in range(self.chrom_size)]
            individual = np.vstack([one_string, two_string])
            init_pop.append(individual)
        return np.array(init_pop)

    def decode(self, pop1):
        fuzzy_fitness = []
        certain_fitness = []
        for individual in pop1:
            fuzzy_completion_time = self.shop.process_decode1(individual)
            fuzzy_fitness.append(fuzzy_completion_time)
            certain_fitness.append(value(fuzzy_completion_time))
        return fuzzy_fitness, certain_fitness

    def selection(self, pop2, fuzzy_fitness, certain_fitness):
        """
        tournament selection + elite_strategy
        """
        pop2 = pop2.tolist()
        sorted_pop = sorted(pop2, key=lambda x: certain_fitness[pop2.index(x)], reverse=False)
        new_pop = sorted_pop[:self.elite_number]
        while len(new_pop) < self.pop_size:
            index1, index2 = random.sample(list(range(10, self.pop_size)), 2)
            if rank(fuzzy_fitness[index1], fuzzy_fitness[index2]) == fuzzy_fitness[index1]:
                new_pop.append(pop[index2])
            else:
                new_pop.append(pop[index1])
        return np.array(new_pop)

    def crossover_machine(self, pop_machine):
        """
        two point crossover (TPX)
        """
        temp = pop_machine.copy().tolist()
        new_pop = []
        while len(temp) != 0:
            parent1, parent2 = random.sample(temp, 2)
            temp.remove(parent1)
            temp.remove(parent2)
            if random.random() < self.cross_rate:
                pos1, pos2 = sorted(random.sample(list(range(self.chrom_size)), 2))
                offspring1 = parent1[:pos1] + parent2[pos1:pos2] + parent1[pos2:]
                offspring2 = parent2[:pos1] + parent1[pos1:pos2] + parent2[pos2:]
            else:
                offspring1 = parent1
                offspring2 = parent2
            new_pop.append(offspring1)
            new_pop.append(offspring2)
        return np.array(new_pop)

    def crossover_job(self, pop_job):
        """
        generalisation of the precedence preservative crossover (PPX)
        """
        temp = pop_job.copy().tolist()
        new_pop = []
        for parent1 in temp:
            if random.random() < self.cross_rate:
                new_individual = []
                parent2 = pop_job[random.randint(0, self.pop_size-1)].tolist()
                string = random.choices([0, 1], k=self.chrom_size)
                for choose in string:
                    if int(choose) == 0:
                        new_individual.append(parent1[0])
                        parent2.remove(parent1[0])
                        parent1 = parent1[1:]
                    else:
                        new_individual.append(parent2[0])
                        parent1.remove(parent2[0])
                        parent2 = parent2[1:]
                new_pop.append(new_individual)
            else:
                new_pop.append(parent1)
        return np.array(new_pop)

    def mutation(self, part):
        """
        swap
        """
        for individual in part:
            if random.random() < self.mutate_rate:
                pos1, pos2 = random.sample(list(range(self.chrom_size)), 2)
                individual[pos1], individual[pos2] = individual[pos2], individual[pos1]
        return part

    @staticmethod
    def elite_strategy(pop3, fitness):
        best_fitness = [np.inf, np.inf, np.inf]
        best_individual = None
        for k, individual in enumerate(pop3):
            if rank(fitness[k], best_fitness) == best_fitness:
                best_fitness = fitness[k]
                best_individual = individual
        return best_individual, best_fitness

2.3 测试结果

用文献[3]中instance1测试,文献中instance1求出最优解[20, 31, 40],本人测试最优解[20, 31, 41]

0:old best:[inf, inf, inf], now best:[47, 70, 89], now mean:99.9475
100:old best:[28, 41, 54], now best:[34, 42, 52], now mean:48.41
200:old best:[25, 38, 46], now best:[25, 38, 47], now mean:38.92
300:old best:[25, 36, 45], now best:[25, 36, 45], now mean:38.2425
400:old best:[21, 33, 44], now best:[21, 33, 44], now mean:35.2775
500:old best:[21, 31, 41], now best:[24, 31, 40], now mean:34.475
600:old best:[21, 31, 41], now best:[21, 31, 42], now mean:34.35
700:old best:[19, 31, 42], now best:[19, 31, 42], now mean:33.5275
800:old best:[20, 31, 41], now best:[19, 31, 42], now mean:32.6575
900:old best:[20, 31, 41], now best:[20, 31, 41], now mean:34.175

模糊甘特图如下
在这里插入图片描述
迭代曲线如下
在这里插入图片描述

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

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

相关文章

软件测试复习07:软件测试过程

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录测试计划测试设计测试执行测试监控测试结束软件测试过程主要有5个阶段&#xff1a;测试计划、测试设…

《深入浅出计算机组成原理》学习笔记 Day3

ELF和静态链接1. 程序执行&#xff1a;编译、链接和装载2. ELF 格式和链接3. 总结延伸参考1. 程序执行&#xff1a;编译、链接和装载 有这么两个C文件&#xff1a; \\ add.c int add(int a, int b) {return a b; }\\ test.c #include <stdio.h> int main() {int a 1;…

JVM学习(三):聊聊内存泄漏(memory leak)

一、什么是内存泄漏&#xff08;memory leak&#xff09;可达性分析算法来判断对象是否是不再使用的对象&#xff0c;本质都是判断一个对象是否还被引用。那么对于这种情况下&#xff0c;由于代码的实现不同就会出现很多种内存泄漏问题&#xff08;让JVM误以为此对象还在引用中…

最新光速配置VScode运行C/C++教程(W11适用)

文章目录1.下载MingW编译器&#xff1a;2.解压7z压缩文件方法3.VScode配置4.下面看看成果&#xff1a;1.下载MingW编译器&#xff1a; 下载地址 往下面拖找到上面这个东西-下载最新版本 2.解压7z压缩文件方法 7z解压程序官网 下它&#xff01;相信这个时候在装的一般都是6…

【ubuntu | cuda】ubuntu22.04 安装cuda11.3方法

every blog every motto: You can do more than you think. 0. 前言 ubuntu22.04 安装cuda11.3方法记录 1. 正文 1.1 方法一&#xff1a; https://developer.nvidia.com/cuda-11.3.0-download-archive?target_osLinux&target_archx86_64&DistributionUbuntu&…

服务网格领域的百花齐放,是否存在一个更优解?

作者lingsamuel&#xff0c;API7.ai 云原生技术专家&#xff0c;Apache APISIX Committer。 作者林志煌&#xff0c;API7.ai 技术工程师&#xff0c;Apache APISIX contributor。 服务网格是一种技术架构&#xff0c;它用于管理微服务系统中各个服务之间的通信&#xff0c;旨在…

关于volatile和gcc 优化的的思考

volatile是一个特征修饰符&#xff08;type specifier&#xff09; volatile的作用是作为指令关键字&#xff0c;确保本条指令不会因编译器的优化而省略&#xff0c;且要求每次直接读值。这是百度百科的介绍&#xff0c;那编译器是具体是怎么优化的呢。我们知道gcc 是有O0 O1 O…

torch.nn.MSELoss扒开看看它

目录官网介绍Toy默认参数定制参数预测问题-线性回归官网介绍 Toy 设X,Y∈Rnd\mathbf{X} , \mathbf{Y} \in \mathbf{R}^{n\times d}X,Y∈Rnd&#xff0c;假设其中X\mathbf{X}X是模型的输入&#xff0c;Y\mathbf{Y}Y是真实标签 默认参数 torch.nn.MSELoss(size_averageNone, r…

【Java IO流】字节流详解

文章目录1. IO 流概述2. IO 流分类3. 字节输出流4. 字节输入流5. 文件拷贝6. IO 流中的异常处理7. 总结Java编程基础教程系列1. IO 流概述 什么是 IO 流&#xff1f; IO 流是存取数据的解决方案&#xff0c;在计算机中数据存放在硬盘的文件中&#xff0c;如果程序需要使用这些…

Gitlab 项目上传到Maven仓库

Gitlab 项目上传到Maven仓库Gitlab 项目上传到Maven仓库1. 生成Deploy tokens2.项目工程AS的build.gradle配置Maven3. 拉取Maven库Gitlab 项目上传到Maven仓库 1. 生成Deploy tokens 项目地址-》Settings-》Repository-》Deploy tokens-》Expand-》输入Name-》Create deploy …

回收租赁商城系统功能拆解10讲-会员等级

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

数据分析面试题--SQL面试题

目录标题1&#xff0c;UNION和JOIN的区别2&#xff0c;连续登录问题3&#xff0c;窗口函数和普通聚合函数的区别4&#xff0c;窗口函数的基本用法5&#xff0c;序号函数:row_number(),rank(),dense_rank()的区别6&#xff0c;窗口函数涉及的一些其他函数7&#xff0c;次日留存率…

CAD软件中如何标注曲线长度?

在CAD设计过程中&#xff0c;如果想要用CAD标注图纸中某一曲线的长度该如何操作呢&#xff1f;今天小编就来给大家分享一个CAD标注曲线长度的小工具&#xff0c;有需要的小伙伴可以一起来看看哦&#xff01; 此插件可以用多种方式标注多段线、样条曲线的长度&#xff0c;并可以…

Go语言笔记:UDP基础使用与广播

文章目录目的基础说明作为服务器使用作为客户端使用广播总结目的 UDP是比较基础常用的网络通讯方式&#xff0c;这篇文章将介绍Go语言中UDP基础使用的一些内容。 本文中使用 Packet Sender 工具进行测试&#xff0c;其官网地址如下&#xff1a; https://packetsender.com/ 基…

知识站点上关于Notes Domino话题几个问答

大家好&#xff0c;才是真的好。 今天周一我们继续不讲技术&#xff0c;介绍一下知识网站上关于Notes/Domino几个有趣问题的讨论。 国内的知识网站头把交椅是知乎&#xff0c;在中文界中是扛把子.不过在国外&#xff0c;最流行的知识网站叫做Quora&#xff0c;上面关于Notes/…

【Java】【系列篇】【Spring源码解析】【三】【体系】【PostProcessors体系】

PostProcessor英文翻译为后置处理器&#xff0c;在Spring体系里面主要针对的对象为Bean和BeanFactory.有着收尾或完善的作用。一、BeanPostProcessor分支 1.1、作用 在Bean对象在实例化和依赖注入完毕后&#xff0c;在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean…

【学习笔记】【Pytorch】十六、模型训练套路

【学习笔记】【Pytorch】十六、模型训练套路一、内容概述二、模型训练套路1.代码实现&#xff1a;CPU版本2.代码实现&#xff1a;优先GPU版本a3.代码实现&#xff1a;优先GPU版本b4.计算测试集上的正确率三、使用免费GPU训练模型一、内容概述 本内容主要是介绍一个完整的模型训…

信用评分分卡简介

背景 随着金融科技初创企业的兴起&#xff0c;过去 5 年中出现了许多新的消费信贷机构&#xff0c;与传统银行展开竞争。他们通常瞄准银行认为规模太小或因金融危机期间发生的后期损失而不得不削减贷款的细分市场。通俗的讲就是消费金融公司瞄准了银行的次贷市场。 这些新的消…

【C语言】文件操作修改通讯录(升级版本)可以存储数据

文件操作的内容&#xff0c;我们在上文已经学习了&#xff0c;那么如果有不明白的小伙伴请看这篇文章 【C语言】小王带您实现文件操作&#xff08;简单图示讲解&#xff09;_小王学代码的博客-CSDN博客 通讯录我们在之前也学习实现了静态、动态通讯录 【C语言】使用C语言实现静…

分享80个PHP源码,总有一款适合您

PHP源码 分享80个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 80个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/1yJ1aR6vt2kDjiVyqj0gPuw?pwdlfl9 提取码&#xff…