workforce4.py


workforce4.py


# !/usr/bin/python #版权2018,Gurobi优化,L狗万app足彩LC #分配工人轮班;每个工人可能在特定的一天上班,也可能不上班。我们使用字典优化来求解模型:#首先,我们最小化松弛量的线性和。然后,我们限制宽松长裤的总数,并最小化一个二次目标,该目标试图平衡员工的工作量。从gurobipy进口* #每个转变所需的工人数量变化,shiftRequirements = multidict({“Mon1”:3,“Tue2”:2,“Wed3”:4,“Thu4”:4,“Fri5”:5“Sat6”:6“Sun7”:5“Mon8”:2,“Tue9”:2,“Wed10”:3,“Thu11”:4,“Fri12”:6“Sat13”:7,“Sun14”:5})#每个工人数量支付一个轮班工作者工作,工资= multidict({“艾米”:10日,“鲍勃”:12,“凯蒂”:10“丹”:8“Ed”:8,“弗雷德”:9,“顾”:11}) #工人可用性可用性= tuplelist(((“艾米”、“Tue2”)(“艾米”、“Wed3”)(“艾米”、“Fri5”)(“艾米”、“Sun7”)(“艾米”、“Tue9”)(“艾米”、“Wed10”)(“艾米”、“Thu11”)(“艾米”、“Fri12”)(“艾米”、“Sat13”)(“艾米”、“Sun14”)(“鲍勃”、“Mon1”)(“鲍勃”、“Tue2”)(“鲍勃”、“Fri5”)(“鲍勃”、“Sat6”)(“鲍勃”、“Mon8”)(“鲍勃”、“Thu11”)(“鲍勃”,Sat13),(“凯西”,“Wed3”)(“凯西”,“Thu4”)(“凯西”,“Fri5”)(“凯西”,“Sun7”)(“凯西”,“Mon8”)(“凯西”,“Tue9”)(“凯西”,“Wed10”)(“凯西”,“Thu11”)(“凯西”,“Fri12”)(“凯西”,“Sat13”)(“凯西”,“Sun14”)(“丹”、“Tue2”)(“丹”、“Wed3”)(“丹”、“Fri5”)(“丹”、“Sat6”)(“丹”、“Mon8”)(“丹”、“Tue9”)(“丹”、“Wed10”),(“丹”、“Thu11”)(“丹”、“Fri12”)(“丹”、“Sat13”)(“丹”、“Sun14”)(“Ed”,“Mon1”)(“Ed”,“Tue2”)(“Ed”,“Wed3”)(“Ed”,“Thu4”)(“Ed”,“Fri5”)(“Ed”,“Sun7”)(“Ed”,“Mon8”)(“Ed”,“Tue9”)(“Ed”,“Thu11”)(“Ed”,“Sat13”)(“Ed”,“Sun14”)(“弗雷德”、“Mon1”)(“弗雷德”、“Tue2”)(“弗雷德”、“Wed3”)(“弗雷德”、“Sat6”)(“弗雷德”、“Mon8”)(“弗雷德”, 'Tue9'), ('Fred', 'Fri12'), ('Fred', 'Sat13'), ('Fred', 'Sun14'), ('Gu', 'Mon1'), ('Gu', 'Tue2'), ('Gu', 'Wed3'), ('Gu', 'Fri5'), ('Gu', 'Sat6'), ('Gu', 'Sun7'), ('Gu', 'Mon8'), ('Gu', 'Tue9'), ('Gu', 'Wed10'), ('Gu', 'Thu11'), ('Gu', 'Fri12'), ('Gu', 'Sat13'), ('Gu', 'Sun14') ]) # Model m = Model("assignment") # Assignment variables: x[w,s] == 1 if worker w is assigned to shift s. # This is no longer a pure assignment model, so we must use binary variables. x = m.addVars(availability, vtype=GRB.BINARY, name="x") # Slack variables for each shift constraint so that the shifts can # be satisfied slacks = m.addVars(shifts, name="Slack") # Variable to represent the total slack totSlack = m.addVar(name="totSlack") # Variables to count the total shifts worked by each worker totShifts = m.addVars(workers, name="TotShifts") # Constraint: assign exactly shiftRequirements[s] workers to each shift s, # plus the slack reqCts = m.addConstrs((slacks[s] + x.sum('*', s) == shiftRequirements[s] for s in shifts), "_") # Constraint: set totSlack equal to the total slack m.addConstr(totSlack == slacks.sum(), "totSlack") # Constraint: compute the total number of shifts for each worker m.addConstrs((totShifts[w] == x.sum(w) for w in workers), "totShifts") # Objective: minimize the total slack # Note that this replaces the previous 'pay' objective coefficients m.setObjective(totSlack) # Optimize def solveAndPrint(): m.optimize() status = m.status if status == GRB.Status.INF_OR_UNBD or status == GRB.Status.INFEASIBLE \ or status == GRB.Status.UNBOUNDED: print('The model cannot be solved because it is infeasible or \ unbounded') exit(1) if status != GRB.Status.OPTIMAL: print('Optimization was stopped with status %d' % status) exit(0) # Print total slack and the number of shifts worked for each worker print('') print('Total slack required: %g' % totSlack.x) for w in workers: print('%s worked %g shifts' % (w, totShifts[w].x)) print('') solveAndPrint() # Constrain the slack by setting its upper and lower bounds totSlack.ub = totSlack.x totSlack.lb = totSlack.x # Variable to count the average number of shifts worked avgShifts = m.addVar(name="avgShifts") # Variables to count the difference from average for each worker; # note that these variables can take negative values. diffShifts = m.addVars(workers, lb=-GRB.INFINITY, name="Diff") # Constraint: compute the average number of shifts worked m.addConstr(len(workers) * avgShifts == totShifts.sum(), "avgShifts") # Constraint: compute the difference from the average number of shifts m.addConstrs((diffShifts[w] == totShifts[w] - avgShifts for w in workers), "Diff") # Objective: minimize the sum of the square of the difference from the # average number of shifts worked m.setObjective(quicksum(diffShifts[w]*diffShifts[w] for w in workers)) # Optimize solveAndPrint()