Movatterモバイル変換


[0]ホーム

URL:


ContentsMenuExpandLight modeDark modeAuto light/dark mode
Gurobi Example Tour
Light LogoDark Logo
Gurobi
Back to top

Workforce5.java#

/* Copyright 2025, Gurobi Optimization, LLC *//* Assign workers to shifts; each worker may or may not be available on a   particular day. We use multi-objective optimization to solve the model.   The highest-priority objective minimizes the sum of the slacks   (i.e., the total number of uncovered shifts). The secondary objective   minimizes the difference between the maximum and minimum number of   shifts worked among all workers.  The second optimization is allowed   to degrade the first objective by up to the smaller value of 10% and 2 */importcom.gurobi.gurobi.*;publicclassWorkforce5{publicstaticvoidmain(String[]args){try{// Sample data// Sets of days and workersStringShifts[]=newString[]{"Mon1","Tue2","Wed3","Thu4","Fri5","Sat6","Sun7","Mon8","Tue9","Wed10","Thu11","Fri12","Sat13","Sun14"};StringWorkers[]=newString[]{"Amy","Bob","Cathy","Dan","Ed","Fred","Gu","Tobi"};intnShifts=Shifts.length;intnWorkers=Workers.length;// Number of workers required for each shiftdoubleshiftRequirements[]=newdouble[]{3,2,4,4,5,6,5,2,2,3,4,6,7,5};// Worker availability: 0 if the worker is unavailable for a shiftdoubleavailability[][]=newdouble[][]{{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 environmentGRBEnvenv=newGRBEnv();// Create initial modelGRBModelmodel=newGRBModel(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=newGRBVar[nWorkers][nShifts];for(intw=0;w<nWorkers;++w){for(ints=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 satisfiedGRBVar[]slacks=newGRBVar[nShifts];for(ints=0;s<nShifts;++s){slacks[s]=model.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,Shifts[s]+"Slack");}// Variable to represent the total slackGRBVartotSlack=model.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,"totSlack");// Variables to count the total shifts worked by each workerGRBVar[]totShifts=newGRBVar[nWorkers];for(intw=0;w<nWorkers;++w){totShifts[w]=model.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,Workers[w]+"TotShifts");}GRBLinExprlhs;// Constraint: assign exactly shiftRequirements[s] workers// to each shift s, plus the slackfor(ints=0;s<nShifts;++s){lhs=newGRBLinExpr();lhs.addTerm(1.0,slacks[s]);for(intw=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 slacklhs=newGRBLinExpr();lhs.addTerm(-1.0,totSlack);for(ints=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 workerfor(intw=0;w<nWorkers;++w){lhs=newGRBLinExpr();lhs.addTerm(-1.0,totShifts[w]);for(ints=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 workersGRBVarminShift=model.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,"minShift");GRBVarmaxShift=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 objectivesmodel.set(GRB.IntAttr.ModelSense,GRB.MINIMIZE);// Set primary objectiveGRBLinExprobj0=newGRBLinExpr();obj0.addTerm(1.0,totSlack);model.setObjectiveN(obj0,0,2,1.0,2.0,0.1,"TotalSlack");// Set secondary objectiveGRBLinExprobj1=newGRBLinExpr();obj1.addTerm(1.0,maxShift);obj1.addTerm(-1.0,minShift);model.setObjectiveN(obj1,1,1,1.0,0.0,0.0,"Fairness");// Save problemmodel.write("Workforce5.lp");// Optimizeintstatus=solveAndPrint(model,totSlack,nWorkers,Workers,totShifts);if(status!=GRB.OPTIMAL)return;// Dispose of model and environmentmodel.dispose();env.dispose();}catch(GRBExceptione){System.out.println("Error code: "+e.getErrorCode()+". "+e.getMessage());}}privatestaticintsolveAndPrint(GRBModelmodel,GRBVartotSlack,intnWorkers,String[]Workers,GRBVar[]totShifts)throwsGRBException{model.optimize();intstatus=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");returnstatus;}if(status!=GRB.Status.OPTIMAL){System.out.println("Optimization was stopped with status "+status);returnstatus;}// Print total slack and the number of shifts worked for each workerSystem.out.println("\nTotal slack required: "+totSlack.get(GRB.DoubleAttr.X));for(intw=0;w<nWorkers;++w){System.out.println(Workers[w]+" worked "+totShifts[w].get(GRB.DoubleAttr.X)+" shifts");}System.out.println("\n");returnstatus;}}

Help and Feedback


[8]
ページ先頭

©2009-2025 Movatter.jp