int solveAndPrint(GRBModel& model, GRBVar& totSlack, int nWorkers, string* Workers, GRBVar* totShifts) throw(GRBException) { model.optimize(); int status = model.get(GRB_IntAttr_Status); if ((status == GRB_INF_OR_UNBD) || (status == GRB_INFEASIBLE) || (status == GRB_UNBOUNDED)) { cout << "The model cannot be solved " << "because it is infeasible or unbounded" << endl; return status; } if (status != GRB_OPTIMAL) { cout << "Optimization was stopped with status " << status << endl; return status; } // Print total slack and the number of shifts worked for each worker cout << endl << "Total slack required: " << totSlack.get(GRB_DoubleAttr_X) << endl; for (int w = 0; w < nWorkers; ++w) { cout << Workers[w] << " worked " << totShifts[w].get(GRB_DoubleAttr_X) << " shifts" << endl; } cout << endl; return status; }
double GurobiSolver::get_value(void *ptr){ int index = *(int*)(ptr); if(index >= 0 && index < variables->size()){ GRBVar v = variables->at(index); return v.get(GRB_DoubleAttr_X); } return 0.0; }
double GurobiSolver::get_value(void *ptr){ int index = *(int*)(ptr); if(index >= 0 && index < variables->size()){ try { GRBVar v = variables->at(index); return v.get(GRB_DoubleAttr_X); } catch (GRBException e) { std::cout << "Gurobi exception getting value: " << e.getErrorCode() << std::endl; std::cout << e.getMessage() << std::endl; } } return 0.0; }
int main(int argc, char *argv[]) { try { GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); // Create variables GRBVar x = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "x"); GRBVar y = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "y"); GRBVar z = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "z"); // Integrate new variables model.update(); // Set objective: maximize x + y + 2 z model.setObjective(x + y + 2 * z, GRB_MAXIMIZE); // Add constraint: x + 2 y + 3 z <= 4 model.addConstr(x + 2 * y + 3 * z <= 4, "c0"); // Add constraint: x + y >= 1 model.addConstr(x + y >= 1, "c1"); // Optimize model model.optimize(); cout << x.get(GRB_StringAttr_VarName) << " " << x.get(GRB_DoubleAttr_X) << endl; cout << y.get(GRB_StringAttr_VarName) << " " << y.get(GRB_DoubleAttr_X) << endl; cout << z.get(GRB_StringAttr_VarName) << " " << z.get(GRB_DoubleAttr_X) << endl; cout << "Obj: " << model.get(GRB_DoubleAttr_ObjVal) << endl; } catch(GRBException e) { cout << "Error code = " << e.getErrorCode() << endl; cout << e.getMessage() << endl; } catch(...) { cout << "Exception during optimization" << endl; } return 0; }
ChannelsFitness ILPChannelingGurobi(DataStructure *dataStructure, double const alpha) { try { unsigned int messageCount; double alphaCoef = alpha; GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); //model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600); ChannelsFitness cfResult; CAMessage *messages; messageCount = static_cast<unsigned int>(AggregateMessages(dataStructure, messages)); vector<int> w(messageCount); transform(messages, messages + messageCount, w.begin(), [](CAMessage &message) { return message.payload; }); int sumW = 0; for (int i = 0; i < messageCount; i++) { for (int j = 0; j < static_cast<int>(messages[i].nodes.size()); j++) { if (dataStructure->nodesOnBothChannels[messages[i].nodes[j]] != 1) { sumW += messages[i].payload; break; } } } if (alphaCoef < 0) alphaCoef = 1.0 / sumW; GRBVar z = model.addVar(0.0, GRB_INFINITY, 0.0, GRB_CONTINUOUS, "z"); GRBVar Pa = model.addVar(0.0, GRB_INFINITY, 0.0, GRB_CONTINUOUS, "Pa"); GRBVar Pb = model.addVar(0.0, GRB_INFINITY, 0.0, GRB_CONTINUOUS, "Pb"); GRBVar Pg = model.addVar(0.0, GRB_INFINITY, 0.0, GRB_CONTINUOUS, "Pg"); vector<GRBVar> Uea(messageCount); vector<GRBVar> Ueb(messageCount); vector<GRBVar> xi(static_cast<unsigned int>(dataStructure->nodeCount)); generate_n(Uea.begin(), messageCount, [&model]() { return model.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, "Uea"); }); generate_n(Ueb.begin(), messageCount, [&model]() { return model.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, "Ueb"); }); generate_n(xi.begin(), dataStructure->nodeCount, [&model]() { return model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "xi"); }); model.update(); model.setObjective(z + alphaCoef * Pg, GRB_MINIMIZE); model.addConstr(Pa <= z); model.addConstr(Pb <= z); model.addConstr(Pa + Pb - sumW == Pg); model.addConstr(expSum(Uea, w) == Pa); model.addConstr(expSum(Ueb, w) == Pb); for (int e = 0; e < messageCount; e++) { for (int i = 0; i < static_cast<int>(messages[e].nodes.size()); i++) // Problem!!! { if (dataStructure->nodesOnBothChannels[messages[e].nodes[i]] != 1) { model.addConstr(xi[messages[e].nodes[i]] - Uea[e] <= 0); model.addConstr(xi[messages[e].nodes[i]] + Ueb[e] >= 1); } } } model.addConstr(xi[0] == 1); model.optimize(); switch (model.get(GRB_IntAttr_Status)) { case GRB_INFEASIBLE: case GRB_UNBOUNDED: cfResult.channelA = cfResult.channelB = cfResult.gateway = -1; return cfResult; case GRB_TIME_LIMIT: if (model.get(GRB_IntAttr_SolCount) <= 0) { cfResult.channelA = cfResult.channelB = cfResult.gateway = -1; return cfResult; } default: break; } for (int i = 0; i < dataStructure->nodeCount; i++) dataStructure->nodesChannel[i] = static_cast<char>(xi[i].get(GRB_DoubleAttr_X)); /*for(i = 0; i < number_variables; i++) { printf("%d ", static_cast<int>(glp_mip_col_val(mip,i+1))); }*/ cfResult.channelA = static_cast<int>(floor(Pa.get(GRB_DoubleAttr_X) + 0.5)); cfResult.channelB = static_cast<int>(floor(Pb.get(GRB_DoubleAttr_X) + 0.5)); cfResult.gateway = static_cast<int>(floor(Pg.get(GRB_DoubleAttr_X) + 0.5)); for (int i = 0; i < dataStructure->nodeCount; i++) { printf("%d ", static_cast<int>(xi[i].get(GRB_DoubleAttr_X))); } printf("\n"); printf("/ %d, %d, %d\n", cfResult.channelA, cfResult.channelB, cfResult.gateway); delete[] messages; return cfResult; } catch (GRBException e) { cout << e.getMessage() << "\n"; } }
int main(int argc, char *argv[]) { GRBEnv* env = 0; GRBConstr* c = 0; GRBVar* v = 0; GRBVar** x = 0; GRBVar* slacks = 0; GRBVar* totShifts = 0; GRBVar* diffShifts = 0; int xCt = 0; try { // Sample data const int nShifts = 14; const int nWorkers = 7; // Sets of days and workers string Shifts[] = { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6", "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13", "Sun14" }; string Workers[] = { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" }; // Number of workers required for each shift double shiftRequirements[] = { 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[][nShifts] = { { 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 } }; // Model env = new GRBEnv(); GRBModel model = GRBModel(*env); model.set(GRB_StringAttr_ModelName, "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 = new GRBVar*[nWorkers]; for (int w = 0; w < nWorkers; ++w) { x[w] = model.addVars(nShifts); xCt++; model.update(); for (int s = 0; s < nShifts; ++s) { ostringstream vname; vname << Workers[w] << "." << Shifts[s]; x[w][s].set(GRB_DoubleAttr_UB, availability[w][s]); x[w][s].set(GRB_CharAttr_VType, GRB_BINARY); x[w][s].set(GRB_StringAttr_VarName, vname.str()); } } // Slack variables for each shift constraint so that the shifts can // be satisfied slacks = model.addVars(nShifts); model.update(); for (int s = 0; s < nShifts; ++s) { ostringstream vname; vname << Shifts[s] << "Slack"; slacks[s].set(GRB_StringAttr_VarName, vname.str()); } // 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 totShifts = model.addVars(nWorkers); model.update(); for (int w = 0; w < nWorkers; ++w) { ostringstream vname; vname << Workers[w] << "TotShifts"; totShifts[w].set(GRB_StringAttr_VarName, vname.str()); } // Update model to integrate new variables model.update(); GRBLinExpr lhs; // Constraint: assign exactly shiftRequirements[s] workers // to each shift s for (int s = 0; s < nShifts; ++s) { lhs = 0; lhs += slacks[s]; for (int w = 0; w < nWorkers; ++w) { lhs += x[w][s]; } model.addConstr(lhs == shiftRequirements[s], Shifts[s]); } // Constraint: set totSlack equal to the total slack lhs = 0; for (int s = 0; s < nShifts; ++s) { lhs += slacks[s]; } model.addConstr(lhs == totSlack, "totSlack"); // Constraint: compute the total number of shifts for each worker for (int w = 0; w < nWorkers; ++w) { lhs = 0; for (int s = 0; s < nShifts; ++s) { lhs += x[w][s]; } ostringstream vname; vname << "totShifts" << Workers[w]; model.addConstr(lhs == totShifts[w], vname.str()); } // Objective: minimize the total slack GRBLinExpr obj = 0; obj += totSlack; model.setObjective(obj); // Optimize int status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts); if (status != GRB_OPTIMAL) { return 1; } // Constrain the slack by setting its upper and lower bounds totSlack.set(GRB_DoubleAttr_UB, totSlack.get(GRB_DoubleAttr_X)); totSlack.set(GRB_DoubleAttr_LB, totSlack.get(GRB_DoubleAttr_X)); // Variable to count the average number of shifts worked GRBVar avgShifts = model.addVar(0, GRB_INFINITY, 0, GRB_CONTINUOUS, "avgShifts"); // Variables to count the difference from average for each worker; // note that these variables can take negative values. diffShifts = model.addVars(nWorkers); model.update(); for (int w = 0; w < nWorkers; ++w) { ostringstream vname; vname << Workers[w] << "Diff"; diffShifts[w].set(GRB_StringAttr_VarName, vname.str()); diffShifts[w].set(GRB_DoubleAttr_LB, -GRB_INFINITY); } // Update model to integrate new variables model.update(); // Constraint: compute the average number of shifts worked lhs = 0; for (int w = 0; w < nWorkers; ++w) { lhs += totShifts[w]; } model.addConstr(lhs == nWorkers * avgShifts, "avgShifts"); // Constraint: compute the difference from the average number of shifts for (int w = 0; w < nWorkers; ++w) { lhs = 0; lhs += totShifts[w]; lhs -= avgShifts; ostringstream vname; vname << Workers[w] << "Diff"; model.addConstr(lhs == diffShifts[w], vname.str()); } // Objective: minimize the sum of the square of the difference from the // average number of shifts worked GRBQuadExpr qobj; for (int w = 0; w < nWorkers; ++w) { qobj += diffShifts[w] * diffShifts[w]; } model.setObjective(qobj); // Optimize status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts); if (status != GRB_OPTIMAL) { return 1; } } catch (GRBException e) { cout << "Error code = " << e.getErrorCode() << endl; cout << e.getMessage() << endl; } catch (...) { cout << "Exception during optimization" << endl; } delete[] c; delete[] v; for (int i = 0; i < xCt; ++i) { delete[] x[i]; } delete[] x; delete[] slacks; delete[] totShifts; delete[] diffShifts; delete env; return 0; }