这个问题简单可以理解为两个过程:对于一系列的任务和多个机台,怎么将每一个任务都和已有的机台匹配。二、对于每一个机台和分配给它的任务,怎么确定各任务的加工顺序。
本文简单介绍一种非常经典的启发式算法-最长处理时间优先Longest Processing Time First(LPT):逻辑是这样的:首先在时刻0将m个最长的加工时长工序任务分配给对应的m个机台。当当前进入加入状态的机台空闲时将剩余任务中的最长加工时长的任务安排给该空闲机台,直至所有任务都被依次分派完毕为止。
需要指出的是LPT只是一个求解问题的方法,但解并不一定是最优解。例如如下问题:
显然,按我们LPT的算法解为15,解如下图所示
但我们可以用枚举法尝试求解其最优解如下,得到最优解为12,如下图
在此类问题中,有一个定理:
定理的证明见参考文献【1】的P115,这里不做赘述。简单理解定理5.1.1,相当于给出了LPT的启发式求解方法的解相对于最优解的上界偏移比例。
第一次尝试代码实现中直接将所有任务作业时间按降序排列,然后奇数列分配给机器1,偶数列分配给机器2,但这并不符合LPT的算法实现逻辑。
def solvePMS(cuss):
# print("Function solvePMS() was called\n")
uavMkspn = [0 for i in range(UAVnum)]
tempuavAssignments = [[] for i in range(UAVnum)]
uavcussArray = []
uavMkspnArray = []
# Read cuss info into uav customer array and uav makespan array
for i in range(len(cuss)):
uavcussArray.append(cuss[i].idNum)
uavMkspnArray.append(data.disMatrix[0][cuss[i].idNum])
# Sort the uavMkspnArray and save their index
tempIndexArray = np.argsort(uavMkspnArray) # get the list of index for UAV_time for each customer
for i in range(len(cuss)):
tempMark = i%UAVnum
for j in range(UAVnum):
if j == tempMark:
uavMkspn[j] += uavMkspnArray[tempIndexArray[i]]
tempuavAssignments[j].append(uavcussArray[tempIndexArray[i]])
print(str(tempuavAssignments))
uavMkspnOut = max(uavMkspn)
# tempMaxIndex = indexofMax(uavMkspn)
# uavAssignmentsOut = tempuavAssignments[0] + tempuavAssignments[1]
return [uavMkspnOut, tempuavAssignments]
修改之后:
def solvePMS(cuss):
# print("Function solvePMS() was called\n")
uavMkspn = [0 for i in range(UAVnum)]
tempuavAssignments = [[] for i in range(UAVnum)]
uavcussArray = []
uavMkspnArray = []
# Read cuss info into uav customer array and uav makespan array
for i in range(len(cuss)):
uavcussArray.append(cuss[i].idNum)
uavMkspnArray.append(data.disMatrix[0][cuss[i].idNum])
# Sort the uavMkspnArray and save their index
tempIndexArray = np.argsort(uavMkspnArray) # get the list of index for UAV_time for each customer
# for i in range(len(cuss)):
# tempMark = i%UAVnum
# for j in range(UAVnum):
# if j == tempMark:
# uavMkspn[j] += uavMkspnArray[tempIndexArray[i]]
# tempuavAssignments[j].append(uavcussArray[tempIndexArray[i]])
tempIndexArray=list(tempIndexArray)
for i in range(UAVnum):
uavMkspn[i] = uavMkspnArray[tempIndexArray[-1]]
tempuavAssignments[i].append(uavcussArray[tempIndexArray[-1]])
tempIndexArray.remove(tempIndexArray[-1])
while len(tempIndexArray) > 0:
if UAVnum == 2:
if uavMkspn[0]>uavMkspn[1]:
uavMkspn[1] += uavMkspnArray[tempIndexArray[-1]]
tempuavAssignments[1].append(uavcussArray[tempIndexArray[-1]])
tempIndexArray.remove(tempIndexArray[-1])
else:
uavMkspn[0] += uavMkspnArray[tempIndexArray[-1]]
tempuavAssignments[0].append(uavcussArray[tempIndexArray[-1]])
tempIndexArray.remove(tempIndexArray[-1])
print(str(tempuavAssignments))
uavMkspnOut = max(uavMkspn)
# tempMaxIndex = indexofMax(uavMkspn)
# uavAssignmentsOut = tempuavAssignments[0] + tempuavAssignments[1]
return [uavMkspnOut, tempuavAssignments]
这里用到了np.argsort()函数用来实现对排序后的索引进行追踪,list【-1】就是最大值的角标索引。
参考文献:
【1】Scheduling Theory, Algorithms, and Systems by Michael L. Pinedo Charper5,P113