scipy求解指派问题

文章目录

  • 1. 指派问题
    • 1.1 问题描述
    • 1.2 数学模型
  • 2. Scipy求解

1. 指派问题

1.1 问题描述

某公司准备指派 n n n个工人 X 1 , X 2 , . . . , X n X_1,X_2,...,X_n X1X2...Xn n n n件工作 Y 1 , Y 2 , . . . , Y n Y_1,Y_2,...,Y_n Y1Y2...Yn,由于每个工人完成不同工作的效率不同,公司希望在所有工作都得到完成的前提下使得效率达到最大考虑。这类指派问题也称为二部图的最小权重匹配问题(minimum weight matching in bipartite graphs)。

一个赋权的完全二部图 G = ( V 1 , V 2 , E ) G=(V_1,V_2,E) G=V1V2E,其中 V 1 = ( X 1 , X 2 , . X n ) V_1=(X_1,X2,.Xn) V1=X1X2.Xn V 2 = ( Y 1 , Y 2 , . . . , Y n ) V_2=(Y_1,Y_2,...,Y_n) V2=Y1Y2...Yn,边 ( X i , Y j ) (X_i,Y_j) (XiYj)上的权重 c i j c_{ij} cij表示工人 X i X_i Xi完成工作 Y j Y_j Yj的效率。指派问题显然等价于在该图中寻找有最小权重的完美匹配。

1.2 数学模型

指派问题可表述为如下0-1规划问题
m i n ∑ i = 1 n ∑ j = 1 n c i j x i j ∑ i = 1 n x i j = 1 , i = 1 , 2 , . . . n ∑ j = 1 n x i j = 1 , j = 1 , 2 , . . . n x i j ∈ { 0 , 1 } min\sum_{i=1}^{n}\sum_{j=1}^{n}{c_{ij} x_{ij}}\\ \sum_{i=1}^{n}x_{ij} =1, \quad i=1,2,...n\\ \sum_{j=1}^{n}x_{ij} = 1, \quad j=1,2,...n\\ x_{ij}\in{\{0,1}\} mini=1nj=1ncijxiji=1nxij=1,i=1,2,...nj=1nxij=1,j=1,2,...nxij{0,1}

2. Scipy求解

  • scipy.optimize.linear_sum_assignment求解指派问题使用的是匈牙利算法,对于数据要求比较苛刻,成本矩阵不能太大,如果是大型矩阵需要先进行稀疏处理,否则求解效率会变低。
  • Scipy官方API
scipy.optimize.linear_sum_assignment()
Solve the linear sum assignment problem.

Parameters:
cost_matrixarray
The cost matrix of the bipartite graph.

maximizebool (default: False)
Calculates a maximum weight matching if true.

Returns:
row_ind, col_indarray
An array of row indices and one of corresponding column indices giving the optimal assignment. The cost of the assignment can be computed as cost_matrix[row_ind, col_ind].sum(). The row indices will be sorted; in the case of a square cost matrix they will be equal to numpy.arange(cost_matrix.shape[0]).
  • python代码示例
import numpy as np
from scipy.optimize import linear_sum_assignment

worker_num = 10  # 员工数量
job_num = 10  # 任务数量
# 随机生成成本矩阵
cost_matrix = np.random.randint(1, 10, size=(worker_num, job_num))

# 优化求解得到最佳分配下的行列索引值
row_ind, col_ind = linear_sum_assignment(cost_matrix)

# 输出结果
print('cost_matrix=\n', cost_matrix)
for i in list(zip(row_ind + 1, col_ind + 1)):
    print(i[0], '->', i[1])
print('min_cost=', cost_matrix[row_ind, col_ind].sum())
  • 结果

scipy求解指派问题_第1张图片

你可能感兴趣的:(运筹优化,scipy,python,算法)