2018-12-11 15:57:58 +08:00
|
|
|
|
''' mbinary
|
|
|
|
|
#########################################################################
|
|
|
|
|
# File : schedule.py
|
|
|
|
|
# Author: mbinary
|
|
|
|
|
# Mail: zhuheqin1@gmail.com
|
2019-01-31 12:09:46 +08:00
|
|
|
|
# Blog: https://mbinary.xyz
|
2018-12-11 15:57:58 +08:00
|
|
|
|
# Github: https://github.com/mbinary
|
|
|
|
|
# Created Time: 2018-11-30 12:00
|
|
|
|
|
# Description:
|
|
|
|
|
#########################################################################
|
|
|
|
|
'''
|
2018-12-11 15:28:05 +08:00
|
|
|
|
'''
|
|
|
|
|
回溯全空间搜索, 剪枝优化
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
设有n个任务由k个可并行工作的机器来完成,完成任务i需要时间为 。试设计一个算法找出完成这n个任务的最佳调度,使完成全部任务的时间最早。
|
|
|
|
|
'''
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-12-11 15:28:05 +08:00
|
|
|
|
from time import time
|
|
|
|
|
from functools import total_ordering
|
|
|
|
|
@total_ordering
|
|
|
|
|
class record:
|
2020-04-15 12:28:20 +08:00
|
|
|
|
def __init__(self, nums=None):
|
2018-12-11 15:28:05 +08:00
|
|
|
|
if nums is None:
|
2020-04-15 12:28:20 +08:00
|
|
|
|
nums = []
|
|
|
|
|
self.nums = nums
|
2018-12-11 15:28:05 +08:00
|
|
|
|
self.sum = sum(nums)
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
|
|
def append(self, x):
|
2018-12-11 15:28:05 +08:00
|
|
|
|
self.nums.append(x)
|
2020-04-15 12:28:20 +08:00
|
|
|
|
self.sum += x
|
|
|
|
|
|
2018-12-11 15:28:05 +08:00
|
|
|
|
def pop(self):
|
|
|
|
|
x = self.nums.pop()
|
2020-04-15 12:28:20 +08:00
|
|
|
|
self.sum -= x
|
2018-12-11 15:28:05 +08:00
|
|
|
|
return x
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
2018-12-11 15:28:05 +08:00
|
|
|
|
def __repr__(self):
|
|
|
|
|
return repr(self.nums)
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
|
|
def __lt__(self, r):
|
|
|
|
|
return self.sum < r.sum
|
|
|
|
|
|
|
|
|
|
def __eq__(self, r):
|
|
|
|
|
return self.sum == r.sum
|
|
|
|
|
|
2018-12-11 15:28:05 +08:00
|
|
|
|
def tolist(self):
|
|
|
|
|
return self.nums.copy()
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
2018-12-11 15:28:05 +08:00
|
|
|
|
def __hash__(self):
|
|
|
|
|
return self.sum
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def schedule(works, k):
|
|
|
|
|
def backtrackSearch(i, lsts):
|
|
|
|
|
nonlocal best, rst
|
|
|
|
|
if i == n:
|
|
|
|
|
cost = max(r.sum for r in lsts)
|
|
|
|
|
if best > cost:
|
|
|
|
|
best = cost
|
2018-12-11 15:28:05 +08:00
|
|
|
|
rst = [st.tolist() for st in lsts]
|
|
|
|
|
else:
|
|
|
|
|
for cur in set(lsts):
|
2020-04-15 12:28:20 +08:00
|
|
|
|
if best > cur.sum+works[i]:
|
2018-12-11 15:28:05 +08:00
|
|
|
|
cur.append(works[i])
|
2020-04-15 12:28:20 +08:00
|
|
|
|
backtrackSearch(i+1, lsts)
|
2018-12-11 15:28:05 +08:00
|
|
|
|
cur.pop()
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
|
|
def findInitial(i, lst):
|
2018-12-11 15:28:05 +08:00
|
|
|
|
nonlocal best
|
2020-04-15 12:28:20 +08:00
|
|
|
|
if i == n:
|
2018-12-11 15:28:05 +08:00
|
|
|
|
cost = max(lst)
|
2020-04-15 12:28:20 +08:00
|
|
|
|
if best > cost:
|
|
|
|
|
best = cost
|
2018-12-11 15:28:05 +08:00
|
|
|
|
else:
|
|
|
|
|
mn = lst[0]
|
|
|
|
|
idx = 0
|
2020-04-15 12:28:20 +08:00
|
|
|
|
visited = set()
|
|
|
|
|
for j, cur in enumerate(lst):
|
2018-12-11 15:28:05 +08:00
|
|
|
|
if cur not in visited:
|
|
|
|
|
visited.add(cur)
|
2020-04-15 12:28:20 +08:00
|
|
|
|
if mn > cur:
|
2018-12-11 15:28:05 +08:00
|
|
|
|
mn = cur
|
|
|
|
|
idx = j
|
2020-04-15 12:28:20 +08:00
|
|
|
|
lst[idx] += works[i]
|
|
|
|
|
findInitial(i+1, lst)
|
|
|
|
|
lst[idx] -= works[i]
|
2018-12-11 15:28:05 +08:00
|
|
|
|
|
|
|
|
|
n = len(works)
|
|
|
|
|
print()
|
2020-04-15 12:28:20 +08:00
|
|
|
|
print('machine Num:', n)
|
|
|
|
|
print('works :', works)
|
|
|
|
|
rst = None
|
|
|
|
|
works.sort(reverse=True) # key step
|
2018-12-11 15:28:05 +08:00
|
|
|
|
best = sum(works[:n-k+1])
|
|
|
|
|
t = time()
|
2020-04-15 12:28:20 +08:00
|
|
|
|
findInitial(0, [0]*k) # key step
|
2018-12-11 15:28:05 +08:00
|
|
|
|
t1 = time()-t
|
2020-04-15 12:28:20 +08:00
|
|
|
|
print('init solution: {} cost time {:.6f}s'.format(best, t1))
|
2018-12-11 15:28:05 +08:00
|
|
|
|
t = time()
|
2020-04-15 12:28:20 +08:00
|
|
|
|
backtrackSearch(0, [record() for i in range(k)])
|
2018-12-11 15:28:05 +08:00
|
|
|
|
t2 = time()-t
|
2020-04-15 12:28:20 +08:00
|
|
|
|
print('final solution: {} cost time {:.6f}s'.format(best, t2))
|
|
|
|
|
print('schedule plan:', rst)
|
|
|
|
|
return best, rst
|
|
|
|
|
|
2018-12-11 15:28:05 +08:00
|
|
|
|
|
2020-04-15 12:28:20 +08:00
|
|
|
|
if __name__ == '__main__':
|
2018-12-11 15:28:05 +08:00
|
|
|
|
from random import randint
|
2020-04-15 12:28:20 +08:00
|
|
|
|
schedule([47, 20, 28, 44, 21, 45, 30, 39, 28, 33], 3)
|
|
|
|
|
schedule([98, 84, 50, 23, 32, 99, 22, 76, 72, 61, 81, 39, 76, 54, 37], 5)
|
|
|
|
|
schedule([39, 39, 23, 45, 100, 69, 21, 81, 39, 55,
|
|
|
|
|
20, 86, 34, 53, 58, 99, 36, 45, 46], 8)
|
2018-12-11 15:28:05 +08:00
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
machine Num: 19
|
|
|
|
|
works : [39, 39, 23, 45, 100, 69, 21, 81, 39, 55, 20, 86, 34, 53, 58, 99, 36, 45, 46]
|
|
|
|
|
|
|
|
|
|
works 经过逆序排序
|
|
|
|
|
init solution: 135 cost time 0.000196s
|
|
|
|
|
final solution: 126 cost time 0.022922s
|
|
|
|
|
schedule plan: [[100, 21], [99, 23], [86, 39], [81, 45], [69, 53], [58, 45, 20], [55, 36, 34], [46, 39, 39]]
|
|
|
|
|
|
|
|
|
|
works 没有经过排序
|
|
|
|
|
init solution: 168 cost time 0.000179s
|
|
|
|
|
final solution: 126 cost time 10.646307s
|
|
|
|
|
schedule plan: [[39, 86], [39, 34, 53], [23, 99], [45, 39, 36], [100, 20], [69, 55], [21, 58, 46], [81, 45]]
|
|
|
|
|
'''
|