复杂的排班规则:
rule1: 员工每天工作时间不能超过8 小时
rule2: 员工连续工作时间不能超过2小时
rule3: 员工连续工作天数不能大于 5 天
rule4: 部门人员薪资要尽可能的最低
rule5: 员工总工作时长要尽可能的低
rule6: 员工每天排的班次数不能超过 3 次
rulen: 其他能想到的规则
复杂的班次规则
rule7: 单个班次时长不能小于 2 小时
假设有A、B、C 三个部门,分别有员工 :
A1、A2、…… An
B1、B2、…… Bn
C1、C2、…… Cn
其中
A 部门的员工,需要尽可能满足 rule 1、rule 2、rule 3、rule 6、必需满足 rule1
B 部门的员工,需要尽可能满足 rule 1、rule 3、rule 5、rule 6、必需满足 rule 2
C 部门的员工,需要尽可能满足 rule3、rule 5、必需满足 rule 4以及未知规则 rule <?>
C部门的员工 C2、C4 , 需要多一个 rule 1,因为他们年纪大了
-
问题分析:
对于以上问题,想要找到一个解决方案, 需要我们为每一个人,去匹配每一个规则,这个本质属于一个求组合的过程(有可能因为需求的调整演变成排列问题,那将会更复杂,暂时不升级),要求在得到所有的可能组合后,再从其中找出一个可行且否最优方案, 并且每一个人的每一次匹配的变化,都有可能对整体排班方案产生全局影响, 这个影响有可能是好的也可能让方案变得更差,假设按基于24小时每天我们设计了40 种工作时段(也有可能会更多),假设 A 部门有20 个员工, 然后我们要给 A 部门的员工排班, 那么至少有有C(40,20)种组合方案,再加上 rule1 的存在, 这种组合方案数又变得不固定了。
在有限的时间内,如果找到最好的方案变成了一个无法解的问题, 我们识别其为 NP 不完全问题。
即:在有限的时间内, 我们无法从海量的可能中挑出最优的那个。
-
解决方案:
面对 NP 不完全问题我们只能找到其近似解。在诸多可能的解决方案中, 我们选择了两阶段寻优算法作为解决方案,即:启发式(FirstFit) + 寻优(禁忌算法)
一阶段启发式,我们使用了 FirstFit 的方式,迅速迭代以求找到一个初步可行解。它至少是一个保底的可行解决方案;
二阶段寻优,使用禁忌算法来对一阶段的结果进行优化。
-
禁忌算法介绍:
邻域
对于组合优化问题,给定任意可行解x,x∈D,D是决策变量的定义域,对于D上的一个映射:N:x∈D→N(x)∈2(D) 其中2(D)表示D的所有子集组成的集合,N(x)成为x的一个邻域,y∈N(x)称为x的一个邻居。
候选集合
候选集合一般由邻域中的邻居组成,可以将某解的所有邻居作为候选集合,也可以通过最优提取,也可以随机提取,例如某一问题的初始解是[1,2,3],若通过两两交换法则生成候选集合,则可以是[1,3,2],[2,1,3],[3,2,1]中的一个或几个。
禁忌表
禁忌表包括禁忌对象和禁忌长度。由于在每次对当前解的搜索中,需要避免一些重复的步骤,因此将某些元素放入禁忌表中,这些元素在下次搜索时将不会被考虑,这些被禁止搜索的元素就是禁忌对象;
禁忌长度则是禁忌表所能接受的最多禁忌对象的数量,若设置的太多则可能会造成耗时较长或者算法停止,若太少则会造成重复搜索。
评价函数
用来评价当前解的好坏,TSP问题中是总旅程距离。
特赦规则
禁忌搜索算法中,迭代的某一步会出现候选集的某一个元素被禁止搜索,但是若解禁该元素,则会使评价函数有所改善,因此我们需要设置一个特赦规则,当满足该条件时该元素从禁忌表中跳出。
终止规则
一般当两次迭代得到的局部最优解不再变化,或者两次最优解的评价函数差别不大,或者迭代n次之后停止迭代,通常选择第三种方法。
禁忌算法的核心思想最精髓的两个点:
一为:迭代:
计算一阶段的结果得分 score, 参考以下伪码思路进行迭代:
我们要给迭代设置一个终止条件,这个条件可以是时间, 也可以是迭代次数。由于计分制度,能够保证每次得到的可行结果一定不会比之前的更差 ,所以这个过程我们理解为:寻优
二为:禁忌表
因为每次 move 都是随机挑选,所以非常有可能会遇到相同的 move,为了避免重复无效的 move 运算,禁忌算法加入了禁忌表(tabuList )的概念, 即:对于遇到已经 move 过的,我们给它缓存起来,再遇到的时候就丢弃掉。
我们下个定义叫《禁忌元素》,比如 把班次 123 匹配给员工 A1,下次随机时又遇到了把班次 123匹配给 A1, 就属于重复运算了, 我们给它记录下来加入到禁忌表,再遇到就不算它,称这个加入禁忌表的组合为《禁忌元素》。
接下来我们做个假设,假设有一个方案:
planok = “把班次 28 匹配给员工 A2” + “把班次 123”匹配给员工 A1" ,是一个最佳组合方案,
但是按照之前的操作, “班次 123 + 员工A1” 还在禁忌表里呢, 我们是得不到这个方案的因为一旦尝试把 “班次 123” 排给 “员工A1” 的时候,就会被禁忌表拦住。
所以禁忌算法的第二个核心思想是:禁忌表的退化,即每个《禁忌元素》都有一个计数,这个计数我们给它一个初始值 n (n 一般按经验取,在实际业务中这个参数可以通过机器学习得到),每次 move 遇到相同的《禁忌元素》时, 就给这个《禁忌元素》的 n 减1 直到 n 变成0, 而一旦 n = 0 了, 这个《禁忌元素》就又被拿出来又能被参与寻优了, 这样我们就又有了得到 planok 的机会。
以上讲了智能排班的背景, 结合案例解释了我们如何通过两阶段算法实现一个排班的寻优
背景:复杂的排班规则:rule1: 员工每天工作时间不能超过8 小时rule2: 员工连续工作时间不能超过2小时rule3: 员工连续工作天数不能大于 5 天rule4: 部门人员薪资要尽可能的最低rule5: 员工总工作时长要尽可能的低rule6: 员工每天排的班次数不能超过 3 次rulen: 其他能想到的规则…复杂的班次规则rule7: 单个班次时长不能小于 2 小时假设有A、B、C 三个部门,分别有员工 :A1、A2、…… AnB1、B2、…… BnC1、C2、…… Cn
商业领域经常会涉及时间序列数据分析需求,例如:餐馆在一年中不同季节的销售情况预测,市场里生鲜商品的供应变化,或者企业售后服务随着节日大促到来的高峰需求变化等等。这些数据,都呈现着非常明显的随时间发生的周期性、季节性变化。
通过对历史数据的分析,预测未来一段时间的变化情况,是时间序列分析中比较常见的一种场景。沃丰科技 [Udesk] WFO(劳动力优化管理)系统中对客服工作量的预估(
智能
预测客服坐席工作量,预估下一时段空闲客服数量等),使用了GaussMind基于时间序列的预测
算法
,相对于以往的时间序列
算法
(
你好,我是徐晓东,笔名燕云长风。大漠穷秋于 2019-03-16 21:22 赠此笔名。
寓意:结合李白著名的边塞诗《关山月》取【燕云长风】—— 长风几万里,吹度玉门关。
写这篇文章之前,酝酿了很久,希望把自己之前遇到的问题及解决方案分享给大家。
那年深秋,我接到了一个开发任务——XXX市公安交通
智能
化管控系统的
排班
管理系统。
最终我选择了angular技术栈来实践,天下武功,唯快不破。
为了大家...
本文件夹为系统源代码,主要完成
排班
功能。
三层模式,包含一个自动
排班
的业务逻辑:按年份自动
排班
,值班员工轮流值班,周六,周日排两班;其余每天一班。
数据库脚本在app_data文件夹 ;三层核心在app_code文件夹。
新手可以看一看
只用于学习交流。
% 初始化
禁忌
表和搜索起点
tabu_list = zeros(num_users, num_freqs);
current_solution = randi([0, 1], num_users, num_freqs);
% 定义
算法
参数
max_iterations = 100; % 最大迭代次数
tabu_tenure = 10; %
禁忌
期限
% 运行
禁忌
搜索
算法
best_solution = current_solution;
best_objective = objective(best_solution);
for i = 1:max_iterations
% 生成新解
new_solution = generate_new_solution(current_solution, tabu_list);
new_objective = objective(new_solution);
% 更新
禁忌
表
tabu_list = update_tabu_list(tabu_list, current_solution, new_solution, tabu_tenure);
% 更新最优解
if new_objective > best_objective
best_solution = new_solution;
best_objective = new_objective;
% 更新当前解
current_solution = new_solution;
% 打印最优解和目标函数值
disp(best_solution);
disp(best_objective);
% 生成新解的函数
function new_solution = generate_new_solution(current_solution, tabu_list)
% 生成新解的代码
% 更新
禁忌
表的函数
function tabu_list = update_tabu_list(tabu_list, current_solution, new_solution, tabu_tenure)
% 更新
禁忌
表的代码
值得注意的是,这只是一个简单的示例代码。实际应用中需要根据具体问题进行调整和优化。