如何在Python中按条件生成0-1矩阵?调度任务场景需求
解决你的8×8调度矩阵生成问题
嘿,咱们来搞定你正在执行的这个调度任务:生成一个8×8的0-1矩阵,要求每行和为1(每天固定选一个时段),同时每列的和尽可能接近1(每个时段分配的天数尽量平均)。本质上这是个近似完美匹配的问题,下面给你分情况的解决方案:
一、理想最优解:生成置换矩阵
这是最完美的情况——每个时段刚好被分配1天,每行每列都只有1个1,完全满足所有要求。实现起来很简单,就是生成一个1-8的随机排列,把每行的1放在排列对应的列位置上:
Python代码示例
import numpy as np # 生成8个位置的随机置换 random_perm = np.random.permutation(8) # 初始化全0矩阵 schedule_matrix = np.zeros((8, 8), dtype=int) # 按置换填充1 for day_idx in range(8): schedule_matrix[day_idx, random_perm[day_idx]] = 1 # 输出结果 print("满足要求的调度矩阵:") print(schedule_matrix)
运行后你会得到类似这样的矩阵(每行每列各一个1):
[[0 0 1 0 0 0 0 0] [0 0 0 0 1 0 0 0] [1 0 0 0 0 0 0 0] [0 0 0 0 0 1 0 0] [0 1 0 0 0 0 0 0] [0 0 0 0 0 0 1 0] [0 0 0 1 0 0 0 0] [0 0 0 0 0 0 0 1]]
二、有约束时的近似最优解
如果因为某些硬性约束(比如某天必须选特定时段)没法生成完美的置换矩阵,那我们可以通过调整让列和尽可能接近1,步骤如下:
- 先按照约束填充每行的1(确保每行只有1个1);
- 计算当前各列的和,找到列和最大的列和列和最小的列;
- 找到一个在“列和最大”列有1的行,把它的1移到“列和最小”的列(前提是这行在目标列原本是0,也就是不破坏每行和为1的规则);
- 重复上述步骤,直到所有列和的差异不超过1(也就是最多只有部分列是0或2,其余都是1)。
伪代码逻辑参考
while 最大列和 - 最小列和 > 1: col_max = 列和最大的列索引 col_min = 列和最小的列索引 # 找到在col_max有1的某一行 row_to_move = 任意满足matrix[row][col_max] == 1的行索引 # 移动该行的1到col_min matrix[row_to_move][col_max] = 0 matrix[row_to_move][col_min] = 1
举个例子:如果初始矩阵里有一列和为2,另一列和为0,执行一次上述操作后,这两列的和都会变成1,完美拉平差异。
三、结果验证
生成矩阵后,你可以用以下方式验证是否符合要求:
- 验证每行和:
np.sum(schedule_matrix, axis=1),结果应该是全为1的数组; - 验证列和:
np.sum(schedule_matrix, axis=0),结果里的数值应该尽可能多的是1,最多只有少数列是0或2(因为总共有8个1,8列的总和固定为8,所以列和的差异最小就是0或1)。
内容的提问来源于stack exchange,提问作者JOHN
相关产品推荐
相关产品推荐

