解码操作是整个遗传算法最重要的一步,在这步里面我们利用配置文件中的信息将染色体解码成一个有向无环图。

在介绍解码操作之前我们先来看一下配置文件,在part1绪论中我们已经介绍了一个车间调度问题的基本信息可以用一个表格来表示:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAARsAAABeCAIAAACcrScdAAAP+0lEQVR4nO2d709T2brH1x/QN33ZFyQmDQkvSMyE8AJCTsoLiBMSSjSEqKQBkkkhjimOEdBQMNfiRLa5c9pg0PE0ehs9t3KmMWfqiY3XzsR6Qj3jnmsNEKcK9RahZygWaUoDdLfruS/KjwIt7nav0jV0fd4pW/rx2fu79157r/UUAYPBIAcqtACDcahgiWIwSMISxWCQhCWKwSAJSxSDQRKWKAaDJCxRDAZJWKIYDJKwRDEYJGGJYjBIwhLFYJCEJYrBIEmaRCEGg5GZXBJFJq15hnJPmvVodgO69ViiCgbNejS7Ad16LFGpxCO+ny3GEctP0xGcF6VUstXDkemfLCNGy8++SDxPSluw0uUMS9QWa4Gnhqau+7+Fpm2dDecc8/k+MLLRw0LgyUDTuXu/LczZdF+ce7yQZzlWupxhiUoSXxofri3vd4biAELAppWdtPoLXfot8NLzodraXucCBoCATSPrsPrX86nGSpc7LFEAADg8PlRVqjZPxQCShwVSXHSGE3mUE6+HQ+6hepna7I1hAICATYMqepyLVLix0mXvVgyJWvdbO2RynX1BAACANZ/lNEJaW0DIo5xoPey3npSVd9rnkud97LOokVJjm6XBjZUuB7ciSNT6K2O1XN5p37zDDrn0VdScaCMeYwPaPmTximuwhIIT7QasdNm7HfpE4XWPqRopT1p9G0dFfGK0Ro5qRqfy/FhIlN76K2O1PGVkEp0aVSOkHp2KFt6NlS4nt0OfqGShS1XNrRqNRqPRtDZUyBAq0btWKNCLT43WIJlSdUKzQ27QtZLfsT8rXf7cDn2i5u3aspRCJ8LOi4qUewMc8fOPjZpKjs88NBCzTU568aD9rAxV6V2hjb8IO3sUSNHjDG9+8Cz/D6PmBMdHMv2GyORf+7r1w4ZvmlUneh9MiHxZJLl0Yj+3MKXDy5P3Brv1Vw0XTqoaLz2YWk5jJ2abnNwOe6KSNyoaW2DjzyGXvgqVXXaFEwCQmHWOGM1jxq9KlBl3uZhtctVLXgS2BvrJkUCN3vURACDhd46YzGN/1paoMiYq/GzwzJhfwABY8D9ok1d02WfFHBlSSyfucwtUukTYNXzGOi0AAKz6rVp56Tl7ILZLTcQ2Obod9kQJPKdERwzuteQfo+OGckW18dX6rk0+t8vFbJO9XoTnVOjIkHsteTR+chtUqNrkWU85OAWeU2ZMlMBzSlmL2bsKAIDfW1uOyLT2IBm3/UqX1eceeOkiPKeSHTN74wAAeNbagsq09vm9//xz2+TodtgThd9Z1FunSGHBrpOX9ToWduzewiVqzWc5jTZ/LV6wd8qrds9I2DdRIAT4J78GBAwAEJsYrSspN4yLGZhLLV02n3vgpcNC4NcnfPLihWNTN+uQyuD+tOv/JmKbHN0Oe6Lgk9ug2qh89Fdjnarb7t+1cwuXKBx1Xy3f+LVhj/F4ebd9Xth597R/olK2CzoHqmqvPA2sEXIDMaUT87kFKx0A4ICz71jtwJPA3h9ltU02boc+UTjmNavrb06GvHb96Xbz671j6MIlCiA2ZVafGp0MzNgvq9vvTu6d6CkqUfHI5N12tUFknMS6fb50oj63YKXDy5PmM+rPxEnENlm6HfpEAcBa0PP3m6a7jzwLaXdrIRMFWAi+enjzhvmRJ5h2p34+UfHI5L3evgdTkTjg4OsX71eJucG+pRP7uYUpHV6evDPQZ52IYMCLky986R74i9kme7diSNRn2LPL8erMk1t3nqeet/J2WIiR25mo1WnHrfuujctC8iox+MP4S57n+adGjThHyW6ZPndlxnH3jmsu1aEApUteefRj4zzP8/96avyG4yO7d2v6bQi4FXeiIh4rx13TNcjlDbprHGf1RAAA1mYsrbKtt+/ptzkAvU8eq5G7pmuQKxt0Bo77myeSAIDEjKVJJq8ZnYgDJPw/dJTKUtZri53VJtEt4+cm3lqajmxPqihM6db8tq9LUSrJh+ypuzXTNgTcijtRGcErrtu3pc1nyaPeyvPvbk9ImQmUz9KFXN/dlzhNKW96B7FbWaLSssyPmN1RSfNZ8ndYRPk7JnGPejORx9JFX46YXkicWpc3vYPYrSxRe8Gxadu1sbeiXqFnJl96Me+Daw9nYnSmPTr94MbYjNS5qvnRO6DdyhKVL2jWo9kN6NbLMVEMBiMTuSRKfGQLCOWeNOvR7AZ067FEFQya9Wh2A7r1WKIKBs16NLsB3XosUeLAYZ/TpCnT2YPEFnwT0cORN3bu65aW1taGCnllB2d/Q6QBJaHSxSPeR1znqRbNqYYKZWUbZ/eKXbe3P+T2bDzie2rU1IpcqSEGlqjPEf6noUpZ0dih+VJJtssPAT3BZztz9uZE8jBdCzj6K9EX7Vapz3/JuAEW/LYz7X+ZSE5RFWYdvSpU2mWV/OgcyOiFxg318oqmM5p6OdEGSSxRIonwnIqyROF1j6mmYfjZ1sxu/M6iLtlagFxQNwCIeIwnGoZ+3pr9iH0WNZKV6Z+FJf9qgntW4DklS5RIDnuihIBNixBKWR6blBSzXCrfbgAwa9MoUerSV4HnlAhlOSk2LcWeKBx0mfRnW9Tc+NJ6ZPJeb3d/T9t5i1fqXv8shz1RgIP/NPUO3HL/vjk4Cbn0VQg1byxHL6gbgBAcv9XbZ3YHNyu24tKXIFRv9kpu5lfkiYp674w8WvDZNEfrLg1e+OahPzr7dODLkq2GPnnj0CdqN9FfuCr5dlNiCeThNgRH+etV6MhmP2dJFHei1l+ZLv1jAc/aNEpUecW1FI97zcdkZAbQ+1NkiVr1W7VymZp7GZL+PI18ooRpa1uZrO67l2ECD0uLOlF49vENxwe84tKXlKgt79Ls7Oivxrpj+7bFEIKOntLsO5UWU6JwbMbaXtYw8PQDET/SiYrOWLvKRHe5+CxFnSgA2Gznm6lB7tri+/n936LgyPz7xax3RvEkCodfcPVNpOIEhEsXD7/8rr6OWJyAJQpg1WtuPoAGubsolkTF3lo7Tm/GCa/6/vf1olRJcqXDsRlrx3bzlhXfi8lFyUdB0ScK+21tpXKdI7T77z++vHWl/+zx+qHnS+mrHPHavu3R97Y19v3oz/r5VVEkCv/72eWvB7evTqte81XrrNQhKqnS4eDPl9u/3b46Jd6Yz/9NVFfbfSn6RIWdPYq9gygc5W+ct818dFxQpH+iiqOe78/f88bwO4u6Iod5Ioc/UXh50vxVmUp7hdtiUPvl8GYj1YK6AeDIa3NbtUo7uG13RfvlkFv6zV+xJyo+NVoja7XM7KokFhb9H8I+W3tlk+VtulcUePXD//1bwBBy6OS5vGMhU/eE3znCDeu/qlXKEFJUai4Oc0arR9Ka8ySS9RJh1+Wyvatz1BYfFReBjy59zR65DE+nCqC3Nuu8zQ33a2tLEUKySk3/cBatY6S45XfORGLG0qToss2FPrz/mOHkj1dcgyVHOT778y7lczto1qPZDejWK2yiVr3mZkW34+Pcw/PXf4nCrl5zSaJTo2pFTq+Daa470K1HsxvQrVfYRMWXxofrG89c6r3lXorDzl5zG+B3FvUXbbZcvn2c5roD3Xo0uwHdevTNlN3Zaw4v2DtzGkQB3XUHuvVodgO69WhL1GavufAzfVmtwT0/beko7/oxkNNglua6A916NLsB3XqUJWqr19zqlKW9WXupW9s3NrX3WxXEQXPdgW49mt2Abj3KEkUUyj1p1qPZDejWY4kqGDTr0ewGdOuxRBUMmvVodgO69fKfqMjL0U5Ns6oUIZlSdUKzwamGCmVF88A9/ndis3okeh44NOvR7AZ06x3g3HNUx/Ep72nx8qT5q1JCK+TSQqju8Yj3Edf9dY9heLjnVC25swChuXMUdxeLe4x/auoxP+ZnI1hY9Lr+OtCotfgIrOkg+Eb0D9pd7HeH7ihSXHTu6tGD/bb2MiKruNNC5pAN/NhV3WOfXwMAwB9dA39CspbRSQJNMgjoUd1dbLNVyxayY702egL/h+4ulmzZkWYG55rPchplXIkoFRJ1j4cc5+UIbU6DSrYfkn1h9Ehf2y1Zj/LuYgACz5W3Gr43cdx/jlp/msp+zWgmin3uecJrrkc75xZtkDxASf5/UiF0WzX50DT6cGrjOuCznEaoNLdZUbuQrEd5dzEAgecqCPQS20uRJ0oI2DplqKLHubjnR8kDlOpE7UDwWlqUssYbnlxfOqciXY/u7mIsURk2yOHf7CTk0lchWWe6tXrJI6BK79q9upcI5OqOhcXfnjt+MOs1zb33+SB17Uc2oK27mMBzR9uvXL/Q2XOFM+iaW/7jIXV9z/+IiYpPjNbIUdpORok35npFhrARgOQTodkJnh9/+t+GlsoTAw/pGV6nQl93sbjH1LzVYSIecvaXleps2Xc32EtRJwrPWlsQKtG7Vvb8KOE11yMkb7fNb3bGjnpMdUev7vfVwjjg6K5ONyRLQx7eWsTmbV1yqp6nbUB5dzEAAAg5dHLW91xqohJh50VFavPrbVamRo8jVD/kTjmnCh/ff9j/AhCPfPAvCqLOwvk4LLDPokYI5bSmeBcE9ejsLoYjs6+9KW2Zkg/TSTwnLeZErXiMx9KOlfHC43Nlisq+/wnmreMYgbrjWXtXBZI1GT2bJ9aATYMQkp2V/kVSxA4LSruL/e7QHd3xaiSZqOw7me6liBOVfENyZGh3dx7Bb++uLm27O7n50Awv/evWwMWzjc1D4xnaua3+Zhvs0/d3NHb/3X9g16iNkd52opJ3qrImywwl7fDp7S72yW042WZ6tv1tNwv2Trm8ivtF+svHIk5UyKGTo52d+uKRGQfXUqXqtqYsfFrmrxtsc35Hd1W9+U26YzXsMV25Nx3FPota9PWBRN1jAfvFdpM7mDws8BLPNSJZQ8bYZwOJSyjN3cVwbHrs8veejZt4vDxxs1VRO/QsSODOtBgTlfDbL7ZpWhsqZAjJKhpaNybItjarjlY095t/mt45WlpbfD8fnrO1K/Y2IUuy8sG3ICRnMIj+uhRCF4Gwz3mzu6X9guGaQXe8lqKvvqS8uxgArAX5+wOd3frhb/vbjrf0/5ebor7nh7S7WAprM5ZWRbttLrxPi/OQS199lHspcrfQPEMZ6Naj2Q3o1qMmUYk35vqqbod/zma4zi8D4NWZJ7fuPA+kDpniE6M1VenmXqSH5roD3Xo0uwHdetQkCi+ODzU3nu3tNY0vYUhesmQ7J9Fin0WdzetgmusOdOvR7AZ061GTqDTgFdft29uJEhbsOvGDKKC77kC3Hs1uQLcezYla5kfM7mg87LpcVn7VvfzGcrK2y57FFzvQXHegW49mN6Bbj9pE4di07drY2xjgVe+99kbtJd2ZvgcTWU2oo7nuQLcezW5At16OiWIwGJnIOlEMBiNnWKIYDJKwRDEYJGGJYjBIwhLFYJCEJYrBIAlLFINBEpYoBoMkLFEMBklYohgMkvw/REofpZeqtm4AAAAASUVORK5CYII=" alt="" />

表5.1

在编程时我们要把这个表格用一个配置文件来存储,这个配置文件可以是一个记事本文件,后缀名是.txt。

下面我们给出上面那个表格对应的配置文件:

Init.txt

2 2
2 1 3 2 2
2 2 5 1 1

可以看到这个配置文件有三行,第一行中的第一个“2”表示有2个工件,第二个“2”表示有2台机器。第二行代表工件1的信息,有五个数字,它们的含义如下:

“2”表示工件1有2道工序,

“1”表示工件1的第一道工序需要在机器1上加工,

“3”表示工件1的第一道工序在机器"1"上加工的时间为3个时间单位

“2”表示工件1的第二道工序需要在机器2上加工

“2”表示工件1的第二道工序在机器2上的加工时间为2个时间单位

第三行表示工件2的全部信息,大家可以参考第二行把第三行的数字各自的含义写出来,在此不再赘述。

在进行解码之前,我们首先要写一个函数把配置文件的信息读到一个python类中,最终输出的类实例I应该有着如下的成员:

jobs=[[(1,3),(2,2)],[(2,5),(1,1)]]

(list中又嵌套两个子list,每个子list对应一个工件的信息,子list中的一个有序偶对应表格中的一列)

n=2(工件的个数)

m=3(机器的个数)

这个python类的代码如下所示:

 class Instance:
"""Class representing an instance of the JSP."""
def __init__(self, jobs, m):
self.jobs = jobs
self.n = len(jobs) # number of jobs
self.m = m # number of machines def __getitem__(self, i):
return self.jobs[i] def __len__(self):
return len(self.jobs)

我们还需要写一个函数来把配置文件txt中的信息读到python中对应的成员变量中即

I = LoadInstance("配置文件.txt");

loadInstance的python代码如下:

 def LoadInstance(fname):
"""Load instance file."""
f = open(fname, 'r')"""打开配置文件 Init.txt"""
head = f.readline().split()"""读入第一行"""
n, m = int(head[0]), int(head[1])"""将工件数和机器数存在n和m两个变量中"""
I = []""" 构造上文中的“jobs列表”"""
for l in f:"""从文件中依次读入每行数据,一行对应一个工件"""
l = l.split()
if len(l) < 3: continue """如果少于3个数则跳过该行"""
ntasks = int(l[0])"""ntasks存放该工件包含的工序道数,Init每行对应一个工件""""
I.append([])"""每行一个子list代表一个工件的信息"""
for j in xrange(ntasks):
mid = int(l[j*2+1])
dur = int(l[j*2+2])
I[-1].append((mid, dur))"""每个工件有多道工序,每个工序对应一个有序偶(机器数,加工时间)"""
return Instance(I, m)"""返回Instance类的一个实例"""

我们在part1绪论部分已经介绍了一个JobShop问题的一个解可以用一个有向无环图来表示,而解的质量即makespan则是这个有向图中从起点S到终点F中所有路径中总完成时间最长的那条路径所对应的完成时间。

通过一条染色体和表格5.1来构造相应的有向无环图的代码如下:

 def ComputeDAG(s, I):
"""s是染色体即工件号的乱序排列,I存储表5.1的信息,格式在上面刚刚介绍过"""
G = [] """构造一个空list来存储图"""
for t in s: G.append([])"""为每道工序在图中用一个节点表示,即每个节点对应一个子list"""
G.append([])"""添加终止节点"""
T = [0 for j in xrange(I.n)]"""初始化一个长度为工件数的全0list"""
last_task_job = [-1 for j in xrange(I.n)]"""构造存储每个工件上一次加入图的工序号,初始化为-1 """"
tasks_resource = [[-1 for j in xrange(I.n)] for m in xrange(I.m)]"""见后面正文部分"""
st = [] "记录每个节点对应的工序在其工件内是第几道工序"
for i in xrange(len(s)):""" 遍历染色体,染色体的下标即为图节点的编号,依次处理图的节点"""
j = s[i]"""提取编号为i的节点对应的工件号"""
t = T[j]""" 辅助变量,记录编号i的节点是j工件内的第几道工序"""
st.append(t)""" 将t存入st"""
r = I[j][t][0]""" 将j工件的第t道工序对应有序偶中的第一个数字,即该工序的机器号存入变量r"""
# 判断j的相对工序号的计数器t的值是否等于j的工序数,若相等则将j的最后一道工序指向终止节点
if t + 1 == len(I[j]): G[-1].append(i)
# 若不是j的第一道工序则将该工序的前一道工序指向代表当前工序的节点i
if t > 0: G[i].append(last_task_job[j])
# 如果之前加入的节点也在使用和j的第t道工序相同的机器r,则将这些节点编号指向当前处理节点i
G[i].extend([tasks_resource[r][j2] for j2 in xrange(I.n)
if j2 != j and tasks_resource[r][j2] > -1])
T[j] = T[j] + 1"""j工件的工序号累加器加1"""
last_task_job[j] = i"""将j工件的上一道工序的节点编号置为当前节点的编号i """
tasks_resource[r][j] = i""" 将j工件中正在使用机器r的工序对应的节点编号置为i"""
return G, st""" 返回图G,和记录每个节点对应的工序在其工件内是第几道工序的 list st"""

特别说明一下第9行task_resource这个list,以表5.1为例它的形式是:

task_resource=[[-1,-1],[-1,-1]]

因为有两台机器,所以task_resource里面有两个子list,又因为有两个工件,所以每个子list里面有两个数字,初始化为-1,以后这个数字存放上一次使用这台机器的工件中的相对工序号。

在构造完有向图之后我们就可以利用这个有向图来计算每个解的适应度,具体算法是动态规划的算法。

 def ComputeStartTimes(s, I):
"""该函数计算图中每个节点(一个节点对应一道工序)的开始时间,最后一个节点存放总的makespan"""
G, st = ComputeDAG(s, I)
C = [0 for t in G]"C用来存放图G中每个节点的开始时间,长度为G的节点个数,初始化为全0"
for i in xrange(len(G)):"""遍历G中每一个节点"""
if len(G[i]) == 0: C[i] = 0""" 如果节点i的前面没有节点指向它,则i的开始时间为0"""
"""否则,节点i的开始时间为所有前面指向它的节点的开始时间+处理时间中最大的那个节点的开始时间+处理时间"""
else: C[i] = max(C[k] + I[s[k]][st[k]][1] for k in G[i])

return C"""返回每个节点的开始时间,最后一个终止节点的开始时间即为makespan"""

遗传算法在JobShop中的应用研究(part 5:解码)的更多相关文章

  1. 遗传算法在JobShop中的应用研究(part1: 绪论)

    1. 什么是JobShop问题 Job,中文翻译成工件.一个工件又由若干道工序加工完成. resource, 资源.在本文的车间调度中资源指的是机器,每道工序要在某个特定机器上加工. Constrai ...

  2. 遗传算法在JobShop中的应用研究(part4:变异)

    下面,我们以车间调度为例来谈谈遗传算法中的另一个重要操作变异.变异操作通常发生在交叉操作之后,它的操作对象是交叉得到的新染色体.在本文中我们通过随机交换染色体的两个位置上的值来得到变异后的染色体,变异 ...

  3. 遗传算法在JobShop中的应用研究(part3:交叉)

    2.交叉 交叉是遗传算法中的一个重要操作,它的目的是从两条染色体中各自取出一部分来组合成一条新的染色体这里,在车间调度中一种常见的交叉方法叫Generalized Order Crossover方法( ...

  4. 遗传算法在JobShop中的应用研究(part 7:整体流程)

    """ pop是种群,种群中的每个个体的形式是,(makespan, 染色体)""" pop = [(ComputeStartTimes(g ...

  5. 遗传算法在JobShop中的应用研究(part 6:结果显示)

    def FormatSolution(s, C, I): T = [0 for j in xrange(I.n)] S = [[0 for t in I[j]] for j in xrange(I.n ...

  6. 遗传算法在JobShop中的应用研究(part 2:编码)

    编码 在上一篇博客中我们讨论了车间调度问题的编码,具体说就是根据工件的个数和每个工件的工序数来生成12122这样的数字排列,具体的说一个工件包含多少道工序,那么这个工件的编号就出现多少次.从12122 ...

  7. (转)RRU交织冗余在LTE-R组网中的应用研究

    RRU交织冗余在LTE-R组网中的应用研究 王 芳1,2 庞萌萌1,2 (1.北京全路通信信号研究设计院集团有限公司,北京 100070; 2.北京市高速铁路运行控制系统工程技术研究中心,北京 100 ...

  8. java中的url 编码与解码

    什么是application/x-www-form-urlencoded字符串? 答:它是一种编码类型.当URL地址里包含非西欧字符的字符串时,系统会将这些字符转换成application/x-www ...

  9. Python中进行Base64编码和解码

    Base64编码 广泛应用于MIME协议,作为电子邮件的传输编码,生成的编码可逆,后一两位可能有“=”,生成的编码都是ascii字符.优点:速度快,ascii字符,肉眼不可理解缺点:编码比较长,非常容 ...

随机推荐

  1. Swift: 比较Swift中闭包传值、OC中的Block传值

    一.介绍 开发者对匿名函数应该很清楚,其实它就是一个没有名字的函数或者方法,给人直观的感觉就是只能看到参数和返回值.在iOS开发中中,它又有自己的称呼,在OC中叫Block代码块,在Swift中叫闭包 ...

  2. haproxy para config

    .. from http://www.cnblogs.com/dkblog/archive/2012/03/13/2393321.html 常用配置选项: OPTION 选项: option http ...

  3. sh脚本异常:/bin/sh^M:bad interpreter: No such file or directory

    在Linux中执行.sh脚本,异常/bin/sh^M: bad interpreter: No such file or directory. 分析:这是不同系统编码格式引起的:在windows系统中 ...

  4. Y-TDC 的一些函数

    typedef void (*func_ptr)(void); func_ptr usm_rom_set_tx2_drive_strength_hs; 定义一个函数指针类型.比如你有三个函数:void ...

  5. SpringMVC之控制器的单例和多例管理

    版权声明:本文为博主原创文章,未经博主允许不得转载. 在使用Spring3对控制器Controller进行bean管理时,如果要对控制器是否单例进行管理. 有两种方式配置多例模式: 1.springX ...

  6. Android -- 思考 -- 为什么要在项目中使用MVP模式

    1,其实有时候一直在找借口不去思考这个问题,总是以赶项目为由,没有很认真的思考这个问题,为什么我们要在项目中使用MVP模式,自己也用MVP也已经做了两个项目,而且在网上也看了不少的文章,但是感觉在高层 ...

  7. 卸载Centos自带open-jdk

    1.rpm查看安装文件 rpm -qa|grep java 2,切换到root用户,卸载 rpm -e --nodeps java-1.7.0-openjdk-headless-1.7.0.75-2. ...

  8. Used Query

    ---  查询 look back 6 days logic period_key. select s.store_id, i.upc, sf.period_key from JNJ_CASINO_H ...

  9. 从零开始调用一个手机号归属地查询API

    自从过上程序员的生活,身边总是或多或少的提及一些API(应用程序接口),网上各种入门教程.实例大把大把,有的只是贴上部分代码,也不给注释, 写Demo的时候连编译都无法通过.下面我从小白开始来介绍下调 ...

  10. python opencv 实现Reinhard颜色迁移算法

    Reinhard颜色迁移算法的过程很简单,流程如下,细节部分见原文,题目为color transfer between images: 将参考图片和目标图片转换到LAB空间下 得到参考图片和目标图片的 ...