Workforce5.java


Workforce5.java


/ *版权所有2021,Gurobi优狗万app足彩化,LLC * / / *分配工人转移;每个工人都可能或可能无法在特定日期上使用。我们使用多目标优化来解决模型。最高优先级目标最小化了松弛的总和(即,未发现的转移总数)。二级目标最大限度地减少了所有工人之间工作的最大和最小班次之间的差异。第二优化被允许将第一个目标降解到较小的值10%和2 * /进口Gurobi。*;公共类WorkForce5 {公共静态void main(String [] args){try {//示例数据//工作者和工人字符串shifts [] = new string [] {m​​on1“,”tue2“,”wed3“,“星期四”,“星期五”,“SAT6”,“Sun7”,“Mon8”,“Tue9”,“Wed10”,“星期四”,“星期五”,“星期五”,“SAT13”,“Sun14”};字符串工人[] =新字符串[] {“amy”,“鲍勃”,“凯茜”,“丹”,“ed”,“fred”,“gu”,“tobi”};int nshifts = shifts.length; int nWorkers = Workers.length; // Number of workers required for each shift double shiftRequirements[] = new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 }; // Worker availability: 0 if the worker is unavailable for a shift double availability[][] = new double[][] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 }, { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 }, { 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1 }, { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; // Create environment GRBEnv env = new GRBEnv(); // Create initial model GRBModel model = new GRBModel(env); model.set(GRB.StringAttr.ModelName, "Workforce5"); // Initialize assignment decision 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. GRBVar[][] x = new GRBVar[nWorkers][nShifts]; for (int w = 0; w < nWorkers; ++w) { for (int s = 0; s < nShifts; ++s) { x[w][s] = model.addVar(0, availability[w][s], 0, GRB.BINARY, Workers[w] + "." + Shifts[s]); } } // Slack variables for each shift constraint so that the shifts can // be satisfied GRBVar[] slacks = new GRBVar[nShifts]; for (int s = 0; s < nShifts; ++s) { slacks[s] = model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, Shifts[s] + "Slack"); } // Variable to represent the total slack GRBVar totSlack = model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "totSlack"); // Variables to count the total shifts worked by each worker GRBVar[] totShifts = new GRBVar[nWorkers]; for (int w = 0; w < nWorkers; ++w) { totShifts[w] = model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, Workers[w] + "TotShifts"); } GRBLinExpr lhs; // Constraint: assign exactly shiftRequirements[s] workers // to each shift s, plus the slack for (int s = 0; s < nShifts; ++s) { lhs = new GRBLinExpr(); lhs.addTerm(1.0, slacks[s]); for (int w = 0; w < nWorkers; ++w) { lhs.addTerm(1.0, x[w][s]); } model.addConstr(lhs, GRB.EQUAL, shiftRequirements[s], Shifts[s]); } // Constraint: set totSlack equal to the total slack lhs = new GRBLinExpr(); lhs.addTerm(-1.0, totSlack); for (int s = 0; s < nShifts; ++s) { lhs.addTerm(1.0, slacks[s]); } model.addConstr(lhs, GRB.EQUAL, 0, "totSlack"); // Constraint: compute the total number of shifts for each worker for (int w = 0; w < nWorkers; ++w) { lhs = new GRBLinExpr(); lhs.addTerm(-1.0, totShifts[w]); for (int s = 0; s < nShifts; ++s) { lhs.addTerm(1.0, x[w][s]); } model.addConstr(lhs, GRB.EQUAL, 0, "totShifts" + Workers[w]); } // Constraint: set minShift/maxShift variable to less <=/>= to the // number of shifts among all workers GRBVar minShift = model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "minShift"); GRBVar maxShift = model.addVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "maxShift"); model.addGenConstrMin(minShift, totShifts, GRB.INFINITY, "minShift"); model.addGenConstrMax(maxShift, totShifts, -GRB.INFINITY, "maxShift"); // Set global sense for ALL objectives model.set(GRB.IntAttr.ModelSense, GRB.MINIMIZE); // Set primary objective GRBLinExpr obj0 = new GRBLinExpr(); obj0.addTerm(1.0, totSlack); model.setObjectiveN(obj0, 0, 2, 1.0, 2.0, 0.1, "TotalSlack"); // Set secondary objective GRBLinExpr obj1 = new GRBLinExpr(); obj1.addTerm(1.0, maxShift); obj1.addTerm(-1.0, minShift); model.setObjectiveN(obj1, 1, 1, 1.0, 0.0, 0.0, "Fairness"); // Save problem model.write("Workforce5.lp"); // Optimize int status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts); if (status != GRB.OPTIMAL) return; // Dispose of model and environment model.dispose(); env.dispose(); } catch (GRBException e) { System.out.println("Error code: " + e.getErrorCode() + ". " + e.getMessage()); } } private static int solveAndPrint(GRBModel model, GRBVar totSlack, int nWorkers, String[] Workers, GRBVar[] totShifts) throws GRBException { model.optimize(); int status = model.get(GRB.IntAttr.Status); if (status == GRB.Status.INF_OR_UNBD || status == GRB.Status.INFEASIBLE || status == GRB.Status.UNBOUNDED ) { System.out.println("The model cannot be solved " + "because it is infeasible or unbounded"); return status; } if (status != GRB.Status.OPTIMAL ) { System.out.println("Optimization was stopped with status " + status); return status; } // Print total slack and the number of shifts worked for each worker System.out.println("\nTotal slack required: " + totSlack.get(GRB.DoubleAttr.X)); for (int w = 0; w < nWorkers; ++w) { System.out.println(Workers[w] + " worked " + totShifts[w].get(GRB.DoubleAttr.X) + " shifts"); } System.out.println("\n"); return status; } }