練習8
分配甲、乙、丙、丁4個人去完成A、B、C、D、E 5項任務,每個人完成各項任務的時間見下表。由於任務數多於人數,故考慮:
(1) 任務E必須完成,其他4項中可任選3項完成;
(2) 其中有一人完成兩項,其他每人完成一項。
試分別確定最優分配方案,使完成任務的總時間為最少。
人員\任務 | A | B | C | D | E |
---|---|---|---|---|---|
甲 | 25 | 29 | 31 | 42 | 37 |
乙 | 39 | 38 | 26 | 20 | 33 |
丙 | 34 | 27 | 28 | 40 | 32 |
丁 | 24 | 42 | 36 | 23 | 45 |
8.1 (1)問題指派分析
為了確定最優分配方案,使完成任務的總時間最少,我們可以按照以下步驟進行求解:
- 確定任務選擇:
- 任務E必須完成,所以必須包含在選擇的任務中。
- 在A、B、C、D四項任務中任選三項,共有\(\binom{4}{3} = 4\)種選擇。
- 即選擇組合為:{A, B, C, E}、{A, B, D, E}、{A, C, D, E}、{B, C, D, E}。
- 任務分配方案:
- 每個任務選擇組合確定後,分配4個人完成這4項任務,計算所有可能的分配情況,選擇總時間最少的方案。
- 計算最優方案:
- 對於每一種任務組合,使用計算機演算法(如動態規劃或組合搜尋)來計算所有可能的分配方案,求出總時間最少的方案。
8.2 (1)問題的Python程式
import itertools
import numpy as np
from scipy.optimize import linear_sum_assignment
# 定義任務時間表
time_table = {
'A': [25, 39, 34, 24],
'B': [29, 38, 27, 42],
'C': [31, 26, 28, 36],
'D': [42, 20, 40, 23],
'E': [37, 33, 32, 45]
}
tasks = ['A', 'B', 'C', 'D', 'E']
persons = [0, 1, 2, 3] # 0: 甲, 1: 乙, 2: 丙, 3: 丁
# 任務組合
task_combinations = [
['A', 'B', 'C', 'E'],
['A', 'B', 'D', 'E'],
['A', 'C', 'D', 'E'],
['B', 'C', 'D', 'E']
]
def calculate_assignment_cost(cost_matrix):
row_ind, col_ind = linear_sum_assignment(cost_matrix)
return cost_matrix[row_ind, col_ind].sum(), list(zip(row_ind, col_ind))
best_time = float('inf')
best_combination = None
best_assignment = None
# 儲存每個組合的最小總時間
combination_times = {}
for comb in task_combinations:
# 構建成本矩陣
cost_matrix = []
for person in persons:
cost_row = []
for task in comb:
cost_row.append(time_table[task][person])
cost_matrix.append(cost_row)
cost_matrix = np.array(cost_matrix)
# 計算最優分配
time, assignment = calculate_assignment_cost(cost_matrix)
combination_times[tuple(comb)] = time
if time < best_time:
best_time = time
best_combination = comb
best_assignment = assignment
# 輸出每個任務組合的最小總時間
print("各任務組合的最小總時間:")
for comb, time in combination_times.items():
print(f"任務組合 {comb}: 最小總時間 {time}分鐘")
# 輸出最優方案
person_names = ['甲', '乙', '丙', '丁']
assignment_str = {best_combination[task]: person_names[person] for person, task in best_assignment}
print("\n最優方案:")
print(f"最優任務組合: {best_combination}")
print(f"最優分配方案: {assignment_str}")
print(f"最少總時間: {best_time}分鐘")
各任務組合的最小總時間:
任務組合 ('A', 'B', 'C', 'E'): 最小總時間 111分鐘
任務組合 ('A', 'B', 'D', 'E'): 最小總時間 105分鐘
任務組合 ('A', 'C', 'D', 'E'): 最小總時間 106分鐘
任務組合 ('B', 'C', 'D', 'E'): 最小總時間 110分鐘
最優方案:
最優任務組合: ['A', 'B', 'D', 'E']
最優分配方案: {'B': '甲', 'D': '乙', 'E': '丙', 'A': '丁'}
最少總時間: 105分鐘
8.3 (2)問題的指派分析
要解決這個問題,我們可以使用組合與排列的方法生成所有可能的任務分配方案,然後計算每個方案的總時間,選擇最小的一個。具體步驟如下:
對4個人中的每一個考慮分配兩個任務,其餘三個人各分配一個任務,共有\(\binom{5}{2} = 10\)。
生成新的成本矩陣,對於每一個人承擔兩個任務的情況,計算出所有可能的任務分配組合。
對每個生成的成本矩陣,使用匈牙利演算法(Hungarian Algorithm)來求解最優任務分配問題。
比較所有情況的最小總時間,找到最優分配方案。
8.4(2)問題的Python程式
import numpy as np
from scipy.optimize import linear_sum_assignment
# 給定的時間表
time_table = {
'A': [25, 39, 34, 24],
'B': [29, 38, 27, 42],
'C': [31, 26, 28, 36],
'D': [42, 20, 40, 23],
'E': [37, 33, 32, 45]
}
tasks = ['A', 'B', 'C', 'D', 'E']
persons = ['甲', '乙', '丙', '丁'] # 0: 甲, 1: 乙, 2: 丙, 3: 丁
# 將time_table轉換為二維陣列
time_matrix = np.array([time_table[task] for task in tasks]).T
# 建立新矩陣並輸出
new_matrices = []
for i in range(time_matrix.shape[0]):
new_row = time_matrix[i, :]
new_matrix = np.vstack([time_matrix, new_row])
new_matrices.append((new_matrix, i))
# 對new_matrices進行指派問題求解並列印每個最優值
best_total_time = float('inf')
best_assignment = None
best_matrix = None
best_row_index = None
for idx, (matrix, row_index) in enumerate(new_matrices):
row_ind, col_ind = linear_sum_assignment(matrix)
total_time = matrix[row_ind, col_ind].sum()
print(f"新矩陣 {idx + 1} 的最優值: {total_time} 分鐘")
if total_time < best_total_time:
best_total_time = total_time
best_assignment = list(zip(row_ind, col_ind))
best_matrix = matrix
best_row_index = row_index
# 輸出最優指派方案和最小值
print("\n最優指派方案:")
for person, task in best_assignment:
person_name = persons[person] if person < len(persons) else '完成兩個任務的人員'
task_name = tasks[task] if task < len(tasks) else '額外的任務'
time_spent = best_matrix[person, task]
print(f"{person_name} 負責任務 {task_name}, 所需時間: {time_spent} 分鐘")
print(f"最小總時間: {best_total_time} 分鐘")
print(f"新增的行: {best_row_index+1},即完成兩個任務的人員: {persons[best_row_index]}")
新矩陣 1 的最優值: 135 分鐘
新矩陣 2 的最優值: 131 分鐘
新矩陣 3 的最優值: 133 分鐘
新矩陣 4 的最優值: 134 分鐘
最優指派方案:
甲 負責任務 B, 所需時間: 29 分鐘
乙 負責任務 C, 所需時間: 26 分鐘
丙 負責任務 E, 所需時間: 32 分鐘
丁 負責任務 A, 所需時間: 24 分鐘
完成兩個任務的人員 負責任務 D, 所需時間: 20 分鐘
最小總時間: 131 分鐘
新增的行: 2,即完成兩個任務的人員: 乙