python分配_确定人员分配-Python

importpandasaspdimportmatplotlib.pyplotaspltimportmatplotlib.datesasdatesimportpulp

staffing_requirements=pd.DataFrame({'Time':['0/1/1900 8:00:00','0/1/1900 9:59:00','0/1/1900 10:00:00','0/1/1900 12:29:00','0/1/1900 12:30:00','0/1/1900 13:00:00','0/1/1900 13:02:00','0/1/1900 13:15:00','0/1/1900 13:20:00','0/1/1900 18:10:00','0/1/1900 18:15:00','0/1/1900 18:20:00','0/1/1900 18:25:00','0/1/1900 18:45:00','0/1/1900 18:50:00','0/1/1900 19:05:00','0/1/1900 19:07:00','0/1/1900 21:57:00','0/1/1900 22:00:00','0/1/1900 22:30:00','0/1/1900 22:35:00','1/1/1900 3:00:00','1/1/1900 3:05:00','1/1/1900 3:20:00','1/1/1900 3:25:00'],'People':[1,1,2,2,3,3,2,2,3,3,4,4,3,3,2,2,3,3,4,4,3,3,2,2,1],})staff_availability=pd.DataFrame({'Person':['C1','C2','C3','C4','C5','C6','C7','C8','C9','C10','C11'],'MinHours':[3,3,3,3,3,3,3,3,3,3,3],'MaxHours':[10,10,10,10,10,10,10,10,10,10,10],'HourlyWage':[26,26,26,26,26,26,26,26,26,26,26],'Availability_Hr':['8-18','8-18','8-18','9-18','9-18','9-18','12-1','12-1','17-3','17-3','17-3'],'Availability_15min_Seg':['1-41','1-41','1-41','5-41','5-41','5-41','17-69','17-79','37-79','37-79','37-79'],})staffing_requirements['Time']=['/'.join([str(int(x.split('/')[0])+1)]+x.split('/')[1:])forxinstaffing_requirements['Time']]staffing_requirements['Time']=pd.to_datetime(staffing_requirements['Time'],format='%d/%m/%Y %H:%M:%S')formatter=dates.DateFormatter('%Y-%m-%d %H:%M:%S')# 15 Minstaffing_requirements=staffing_requirements.groupby(pd.Grouper(freq='15T',key='Time'))['People'].max().ffill()staffing_requirements=staffing_requirements.reset_index(level=['Time'])staffing_requirements.index=range(1,len(staffing_requirements)+1)staff_availability.set_index('Person')staff_costs=staff_availability.set_index('Person')[['MinHours','MaxHours','HourlyWage']]availability=staff_availability.set_index('Person')[['Availability_15min_Seg']]availability[['first_15min','last_15min']]=availability['Availability_15min_Seg'].str.split('-',expand=True).astype(int)availability_per_member=[pd.DataFrame(1,columns=[idx],index=range(row['first_15min'],row['last_15min']+1))foridx,rowinavailability.iterrows()]availability_per_member=pd.concat(availability_per_member,axis='columns').fillna(0).astype(int).stack()availability_per_member.index.names=['Timeslot','Person']availability_per_member=(availability_per_member.to_frame().join(staff_costs[['HourlyWage']]).rename(columns={0:'Available'}))''' Generate shift times based off availability '''prob=pulp.LpProblem('CreateStaffing',pulp.LpMinimize)# Minimize coststimeslots=staffing_requirements.index

persons=availability_per_member.index.levels[1]# A member is either staffed or is not at a certain timeslotstaffed=pulp.LpVariable.dicts("staffed",((timeslot,staffmember)fortimeslot,staffmemberinavailability_per_member.index),lowBound=0,cat='Binary')# Objective = cost (= sum of hourly wages)prob+=pulp.lpSum([staffed[timeslot,staffmember]*availability_per_member.loc[(timeslot,staffmember),'HourlyWage']fortimeslot,staffmemberinavailability_per_member.index])# Staff the right number of peoplefortimeslotintimeslots:prob+=(sum([staffed[(timeslot,person)]forpersoninpersons])==staffing_requirements.loc[timeslot,'People'])# Do not staff unavailable personsfortimeslotintimeslots:forpersoninpersons:ifavailability_per_member.loc[(timeslot,person),'Available']==0:prob+=staffed[timeslot,person]==0# Do not underemploy peopleforpersoninpersons:prob+=(sum([staffed[(timeslot,person)]fortimeslotintimeslots])>=staff_costs.loc[person,'MinHours']*4)# timeslot is 15 minutes => 4 timeslots = hour# Do not overemploy peopleforpersoninpersons:prob+=(sum([staffed[(timeslot,person)]fortimeslotintimeslots])<=staff_costs.loc[person,'MaxHours']*4)# timeslot is 15 minutes => 4 timeslots = hourprob.solve()print(pulp.LpStatus[prob.status])output=[]fortimeslot,staffmemberinstaffed:var_output={'Timeslot':timeslot,'Staffmember':staffmember,'Staffed':staffed[(timeslot,staffmember)].varValue,}output.append(var_output)output_df=pd.DataFrame.from_records(output)#.sort_values(['timeslot','staffmember'])output_df.set_index(['Timeslot','Staffmember'],inplace=True)ifpulp.LpStatus[prob.status]=='Optimal':print(output_df)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值