/* Copyright 2025, Gurobi Optimization, LLC *//* Assign workers to shifts; each worker may or may not be available on a particular day. If the problem cannot be solved, relax the model to determine which constraints cannot be satisfied, and how much they need to be relaxed. */importcom.gurobi.gurobi.*;publicclassWorkforce3{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"};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};// Amount each worker is paid to work one shiftdoublepay[]=newdouble[]{10,12,10,8,8,9,11};// 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},{1,1,1,0,1,1,1,1,1,1,1,1,1,1}};// ModelGRBEnvenv=newGRBEnv();GRBModelmodel=newGRBModel(env);model.set(GRB.StringAttr.ModelName,"assignment");// Assignment variables: x[w][s] == 1 if worker w is assigned// to shift s. Since an assignment model always produces integer// solutions, we use continuous variables and solve as an LP.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],pay[w],GRB.CONTINUOUS,Workers[w]+"."+Shifts[s]);}}// The objective is to minimize the total pay costsmodel.set(GRB.IntAttr.ModelSense,GRB.MINIMIZE);// Constraint: assign exactly shiftRequirements[s] workers// to each shift sfor(ints=0;s<nShifts;++s){GRBLinExprlhs=newGRBLinExpr();for(intw=0;w<nWorkers;++w){lhs.addTerm(1.0,x[w][s]);}model.addConstr(lhs,GRB.EQUAL,shiftRequirements[s],Shifts[s]);}// Optimizemodel.optimize();intstatus=model.get(GRB.IntAttr.Status);if(status==GRB.UNBOUNDED){System.out.println("The model cannot be solved "+"because it is unbounded");return;}if(status==GRB.OPTIMAL){System.out.println("The optimal objective is "+model.get(GRB.DoubleAttr.ObjVal));return;}if(status!=GRB.INF_OR_UNBD&&status!=GRB.INFEASIBLE){System.out.println("Optimization was stopped with status "+status);return;}// Relax the constraints to make the model feasibleSystem.out.println("The model is infeasible; relaxing the constraints");intorignumvars=model.get(GRB.IntAttr.NumVars);model.feasRelax(0,false,false,true);model.optimize();status=model.get(GRB.IntAttr.Status);if(status==GRB.INF_OR_UNBD||status==GRB.INFEASIBLE||status==GRB.UNBOUNDED){System.out.println("The relaxed model cannot be solved "+"because it is infeasible or unbounded");return;}if(status!=GRB.OPTIMAL){System.out.println("Optimization was stopped with status "+status);return;}System.out.println("\nSlack values:");GRBVar[]vars=model.getVars();for(inti=orignumvars;i<model.get(GRB.IntAttr.NumVars);++i){GRBVarsv=vars[i];if(sv.get(GRB.DoubleAttr.X)>1e-6){System.out.println(sv.get(GRB.StringAttr.VarName)+" = "+sv.get(GRB.DoubleAttr.X));}}// Dispose of model and environmentmodel.dispose();env.dispose();}catch(GRBExceptione){System.out.println("Error code: "+e.getErrorCode()+". "+e.getMessage());}}}