admin管理员组

文章数量:1794759

写给那些准备入门车间调度问题的小伙伴,关于代码编写以及高效利用他人代码的方法(不要让代码能力限制了你的科研能力)

写给那些准备入门车间调度问题的小伙伴,关于代码编写以及高效利用他人代码的方法(不要让代码能力限制了你的科研能力)

        个人运作这个CSDN也有一年了,这一年中遇到很多人问我代码的问题,尤其是做车间调度的同学,大部分同学都是没有编程经验的,很多时候无从下手,不知道从什么地方开始编,今天就讲讲我的一些经验。

1  编码流程

        我比较喜欢把算法和模型分开,这样的话你修改算法或修改模型就很方便,只要接口做好就好了,通常,我建议先把模型搭建好,然后再加入算法进行求解。比如你是要求解JSP问题,首先确定是单目标还是多目标、动态调度还是静态调度、考虑什么样的约束条件,解码采用那种方式,贪婪解码还是怎样,这样就把模型搭建好了,然后是算法,算法有那些模块,比如你要使用GA,那么就有编码,解码,交叉,变异,从零到一,必然应该从编码开始,之后别的模块再写起来,最后把所有的连接起来就可以了。

2 模型构建

        为什么说要先将模型编好,然后在考虑算法呢,现有车间调度的研究开源还是较少的,而且考虑约束条件不同,环境便会改变,万变不离其中,只要是车间调度问题,便一定有机器、工件,或针对问题的不同,还考虑夹具、AGV、人等相关因素,我一般都喜欢将这些封装成一个类,然后解码就只需在机器或其他上加相应的时间,和工作印迹,以往我的文章也可以看出,具体模块设置已上传Github,需要可至下载:

Aihong-Sun/Shop_Floor_Item: this repo is use to share item of Shop Floor (github)github/Aihong-Sun/Shop_Floor_Item/blob/main/AGV.py        具体使用,调用即可,然后建立调度模型,一个考虑AGV和机器联合调度框架如下:

from *** import Job from *** import AGV from *** import Machine class Shop_Floor_Env: def __init__(self, ): self. Create_Item() def Create_MA(self): self.Machines = [] for i in range(self.M_num): M = Machine(i) self.Machines.append(M) self.AGVs=[] for j in range(self.AGV_num): A = AGV(j) self.AGVs.append(A) #完工时间 def C_max(self): t=0 for J in self.Jobs: if t<J.end: t=J.end return t #运输时间 def T_trans(self): t=0 for agv in self.AGVs: for using_time in agv.using_time: t=t+using_time[1]-using_time[0] return t def Create_Job(self): self.Jobs = [] for k in range(self.J_num): J = Job(k, self.PT[k]) self.Jobs.append(J) def Create_Item(self): self.Create_MA() self.Create_Job() #在此处进行模型构建,加入约束条件等,然后将时间放进相应模块的start、end进行记录 def scheduling(self,): pass 3 算法构建

        在搭建好模型后,算法就很简单了,算法的初次学习,不妨参考一下鲁迅先生的《拿来主义》,“窗外有两个树,一棵是枣树,另外一颗还是棵树”,噢不对,跑偏了,哈哈哈。应该是:“所以我们要运用脑髓,放出眼光,自己来拿!”、“我们要或使用,或存放,或毁灭。那么,主人是新主人,宅子也就会成为新宅子。”,同样,在面对这个问题,算法也是一样,目前很多算法,无论启发式算法、强化学习算法,尤其深度强化学习的研究,在别的问题上已经先行,开源代码也很健全,那么这个时候,如果你还想着自己闭门造车,从理论开始自己写的话,那可能就太慢了,而且效果未必会好,我们可以找找已有的算法实现,看看人家是怎么做的,接口怎么样,然后把自己的模型跟该算法的接口做好,第一步实现就没问题了,这就是拿来主义,但是要会拿会用才行,一个算法怎么改呢,首先你要知道对方用这个算法的问题部分是哪个部分,然后把别人 的问题抛弃,加入你的问题,你的问题怎么适用这个算法,做好接口就好了。

        比如前段时间,有人找我写了一个灰狼优化算法求解一个再制造选配问题,对于这个问题,我是很陌生了,灰狼算法和再制造选配我都不熟悉,那这应该怎么做呢?

        我按照模型、算法分开实现,用了一天时间就复现出来了,当然,这不是说为了吹牛说自己快,只是想告诉大家,这样做复现论文是很快的,你想,平时看论文的时候,很多问题模型大同小异,只是算法更换或修改,如果你每次复现都从头开始,有多少的时间能做,对吧。

        复现的论文为:

 但将原文的粒子群算法换为了灰狼算法,

首先,将问题模型搭建起来,模型主要包括的模块就有,部件,比如:主轴、齿轮,建立对应模块的编码,然后整体模型是部件的装配,目标为:装配精度和成本,建立这个模型:

from Test_data import A0,target_size,Size,Cost,delta_y,Nam_Lis from parts import Spindle,Gear class Assemble: def __init__(self,A0,target_size,Size,Cost,delta_y,Nam_Lis): self.Nam_Lis=Nam_Lis self.delta_y=delta_y self.A0=A0 self.target_size=target_size self.Size=Size self.Cost=Cost self.Create_parts() self.Tdelta_t=0.020 #这个根据原文要求所定,即最大间隙不应超过0.020mm. def Create_parts(self): self.Spindles=[] #里面装CAK6150主轴类 self.Gear1s=[] #里面装02065L1齿轮类 self.Gear2s=[] #里面装02405L齿轮类 for i in range(len(self.A0)): if i==0: #第一位为主轴 for j in range(len(self.Cost[i])): Sp=Spindle(self.Nam_Lis[i][j],self.A0[i],self.target_size[i][0],self.target_size[i][1], self.Size[i][0][j],self.Size[i][1][i],self.Cost[i][j],self.delta_y[i][0],self.delta_y[i][1]) self.Spindles.append(Sp) elif i==1: for k in range(len(self.Cost[i])): g1=Gear(self.Nam_Lis[i][k],self.A0[i],self.target_size[i][0],self.Size[i][0][k],self.Cost[i][k],self.delta_y[i][0]) self.Gear1s.append(g1) else: for k in range(len(self.Cost[i])): g2=Gear(self.Nam_Lis[i][k],self.A0[i],self.target_size[i][0],self.Size[i][0][k],self.Cost[i][k],self.delta_y[i][0]) self.Gear2s.append(g2) #封闭环尺寸链约束函数 def Dimension_chain(self,S,G1,G2): ''' :param S: 为一个主轴类 :param G1: 为齿轮1类 :param G2: 为齿轮2类 :return delta_t: 封闭尺寸偏差 ''' t1=S.D1-G1.D t2=S.D2-G2.D T1=bool(t1<=self.Tdelta_t) T2=bool(t2<=self.Tdelta_t) if T1 and T2: return True #如何满足装配尺寸链要求,返回True else: return False #质量损失成本函数 def Quality_loss_fun(self,Lis): ''' :param Lis: :return Loss: ''' Loss=0 for i in range(len(Lis)): for j in range(len(Lis[i])): if j==0: #当部件为主轴时 k1=Lis[i][j].A0/Lis[i][j].y1 k2=Lis[i][j].A0/Lis[i][j].y1 L_y1=k1*pow((Lis[i][j].D1-Lis[i][j].target_D1),2) # L_y2 = k2 * pow((Lis[i][j].D2 - Lis[i][j].target_D2),2) # Loss=Loss+L_y1+L_y2 else: k=Lis[i][j].A0/Lis[i][j].y L_y = k * (Lis[i][j].D - Lis[i][j].target_D) Loss+=L_y return Loss #剩余件成本函数 def Cost_of_surplus_parts(self,Lis): ''' :param Lis: :return: ''' Ji=0 #参与装配的再制造件i的加工成本 for Li in Lis: Ji+=Li.Processing_cost G=0 #未参与装配的再制造件及再利用件的剩余再制造零件的总成本 for Si in self.Spindles: if Si not in Lis and 'N'not in Si.Nam: #判断主轴是再利用或再制造件且没有被利用的件 G+=Si.r for Sj in self.Gear1s: if Sj not in Lis and 'N' not in Sj.Nam: # 判断齿轮1是再利用或再制造件且没有被利用的件 G += Sj.r for Sk in self.Gear2s: if Sk not in Lis and 'N' not in Sk.Nam: # 判断齿轮1是再利用或再制造件且没有被利用的件 G += Sk.r C=Ji+G return C def show(self,Lis): for i in range(len(Lis)): print('第',i+1,'个零件组合') for j in range(len(Lis[i])): if j==0: print(self.Spindles[Lis[i][j]].Nam) elif j==1: print(self.Gear1s[Lis[i][j]].Nam) else: print(self.Gear2s[Lis[i][j]].Nam) Ass=Assemble(A0,target_size,Size,Cost,delta_y,Nam_Lis)

然后就是拿来主义——算法,哈哈哈,首先了解一下这个算法的基本原理:

【优化算法】简述灰狼优化算法(GWO)原理_蓝色蛋黄包的博客-CSDN博客_灰狼算法blog.csdn/haha0332/article/details/88805910然后再Github上找一个合适的算法:

matikuto/Python-implementation-of-Gray-Wolf-Optimizer-and-Improved-Gray-Wolf-Optimizer: Implementation of GWO and i-GWO with Python 3.9 (github)github/matikuto/Python-implementation-of-Gray-Wolf-Optimizer-and-Improved-Gray-Wolf-Optimizer修改编码方式(原编码方式为一层,此处修改为三层),即在wolf函数处修改自己编解码方式:

import random from Assembly import Ass from Test_data import Num_part class wolf: def __init__(self,Lis,minx,maxx,position=None): ''' :param Lis: 传入的是各零件的个数,例如本文的实验中主轴有6个,齿轮1、齿轮2分别有10个,则Lis=[6,10,10] minx,maxx:分别表示每个元素的取值范围 ''' self.Lis=Lis if position==None: self.Position = [] for i in Lis: #这里参考我写的程序说明中的编码方式 Pi=[] for j in range(i): Pi.append(((maxx - minx) * random.random() + minx)) self.Position.append(Pi) else: self.Position=position self.fit() def Decode(self): #按照程序说明中的解码部分进行理解 Pos_change=[] for Pi in self.Position: Posi=dict(enumerate(Pi)) Posi = sorted(Posi.items(), key=lambda x: x[1], reverse=True) Pos_change.append(Posi) min_l=min(self.Lis) #找出最小的零件个数,即最多可装配min_l个装配体 selective_scheme=[] #选配方案 for i in range(min_l): Parts=[] for j in range(len(Pos_change)): pc=Pos_change[j][i][0] Parts.append(pc) selective_scheme.append(Parts) return selective_scheme def fit(self): selective_scheme=self.Decode() #判断组合是否满足封闭尺寸链 Meet_quality=[] #存入满足封闭尺寸链的零件组合 Use_parts=[] #参与使用的零件 for Si in selective_scheme: Part_Lis=[] #一组零件组合 for i in range(len(Si)): if i==0: Part_Lis.append(Ass.Spindles[Si[i]]) #主轴 elif i==1: Part_Lis.append(Ass.Gear1s[Si[i]]) #齿轮1 else: Part_Lis.append(Ass.Gear2s[Si[i]]) #齿轮2 if Ass.Dimension_chain(Part_Lis[0],Part_Lis[1],Part_Lis[2]): #判断是否满足封闭尺寸链 Meet_quality.append(Part_Lis) Use_parts.extend(Part_Lis) Loss=Ass.Quality_loss_fun(Meet_quality) C=Ass.Cost_of_surplus_parts(Use_parts) self.fitness=Loss+C w=wolf(Num_part,-2,2) #在这里,minx,maxx取-2,2

然后主函数,部分修改即可,然后一个可调式的完整代码就完成啦。还要修改的话,就广泛阅读论文了。

具体改编代码可见:

Aihong-Sun/Gray_wolf_optimizer_for_selectibe_assmbly: this repo proposes a optimal selective assembly Method for remanufacturing product considering quality,cost and resource utilization (github)github/Aihong-Sun/Gray_wolf_optimizer_for_selectibe_assmbly不要让代码能力限制了你的科研能力,哈哈哈!

其他,如强化学习等求解车间调度问题同样学习方法,祝大家科研顺利哟!

本文标签: 代码能力高效车间小伙伴