23#ifdef STORM_HAVE_GUROBI
30#ifdef STORM_HAVE_GUROBI
31GRBenv* GurobiEnvironment::operator*() {
32 STORM_LOG_ASSERT(initialized,
"Gurobi Environment has not been initialized.");
39#ifdef STORM_HAVE_GUROBI
41 int error = GRBloadenv(&env,
"");
42 if (error || env ==
nullptr) {
43 STORM_LOG_THROW(error != 10009, storm::exceptions::GurobiLicenseException,
44 "Gurobi License Issue. Could not initialize Gurobi environment (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
46 "Could not initialize Gurobi environment (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
50 error = GRBsetintparam(env,
"Method",
static_cast<int>(gurobiSettings.
getMethod()));
52 "Unable to set Gurobi Parameter Method (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
57 "Unable to set Gurobi Parameter Threads (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
59 error = GRBsetintparam(env,
"MIPFocus", gurobiSettings.
getMIPFocus());
61 "Unable to set Gurobi Parameter MIPFocus (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
65 "Unable to set Gurobi Parameter ConcurrentMIP (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
70 "Unable to set Gurobi Parameter IntFeasTol (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
76 return integerTolerance;
80#ifdef STORM_HAVE_GUROBI
81 int error = GRBsetintparam(env,
"OutputFlag", set);
83 "Unable to set Gurobi Parameter OutputFlag (" << GRBgeterrormsg(env) <<
", error code " << error <<
").");
89#ifdef STORM_HAVE_GUROBI
91template<
typename ValueType,
bool RawMode>
94 :
LpSolver<ValueType, RawMode>(optDir), model(nullptr), environment(environment), nextVariableIndex(0) {
97 error = GRBnewmodel(**environment, &model, name.c_str(), 0,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
99 "Could not initialize Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
102template<
typename ValueType,
bool RawMode>
108template<
typename ValueType,
bool RawMode>
110 : GurobiLpSolver(environment,
"", optDir) {
114template<
typename ValueType,
bool RawMode>
120template<
typename ValueType,
bool RawMode>
126template<
typename ValueType,
bool RawMode>
128 int error = GRBupdatemodel(model);
130 "Unable to update Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
133 this->currentModelHasBeenOptimized =
false;
136template<
typename ValueType,
bool RawMode>
140 return GRB_CONTINUOUS;
150template<
typename ValueType,
bool RawMode>
152 std::optional<ValueType>
const& lowerBound,
153 std::optional<ValueType>
const& upperBound,
154 ValueType objectiveFunctionCoefficient) {
156 if constexpr (RawMode) {
157 resultVar = nextVariableIndex;
159 resultVar = this->declareOrGetExpressionVariable(name, type);
162 STORM_LOG_ASSERT(variableToIndexMap.count(resultVar) == 0,
"Variable " << resultVar.getName() <<
" exists already in the model.");
163 this->variableToIndexMap.emplace(resultVar, nextVariableIndex);
164 if (!incrementalData.empty()) {
165 incrementalData.back().variables.push_back(resultVar);
177 "Could not create binary Gurobi variable (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
181struct GurobiConstraint {
182 std::vector<int> variableIndices;
183 std::vector<double> coefficients;
188template<
typename ValueType,
bool RawMode>
190 std::map<storm::expressions::Variable, int>
const& variableToIndexMap,
double integerTolerance) {
191 GurobiConstraint gurobiConstraint;
193 if constexpr (RawMode) {
195 relationType = constraint.relationType;
196 gurobiConstraint.variableIndices.insert(gurobiConstraint.variableIndices.end(), constraint.lhsVariableIndices.begin(),
197 constraint.lhsVariableIndices.end());
198 gurobiConstraint.coefficients.reserve(constraint.lhsCoefficients.size());
199 for (
auto const& coef : constraint.lhsCoefficients) {
203 STORM_LOG_THROW(constraint.isRelationalExpression(), storm::exceptions::InvalidArgumentException,
"Illegal constraint is not a relational expression.");
204 storm::expressions::LinearCoefficientVisitor::VariableCoefficients leftCoefficients =
205 storm::expressions::LinearCoefficientVisitor().getLinearCoefficients(constraint.getOperand(0));
206 storm::expressions::LinearCoefficientVisitor::VariableCoefficients rightCoefficients =
207 storm::expressions::LinearCoefficientVisitor().getLinearCoefficients(constraint.getOperand(1));
210 relationType = constraint.getBaseExpression().asBinaryRelationExpression().getRelationType();
211 int len = std::distance(leftCoefficients.
begin(), leftCoefficients.
end());
212 gurobiConstraint.variableIndices.reserve(len);
213 gurobiConstraint.coefficients.reserve(len);
214 for (
auto const& variableCoefficientPair : leftCoefficients) {
215 auto variableIndexPair = variableToIndexMap.find(variableCoefficientPair.first);
216 gurobiConstraint.variableIndices.push_back(variableIndexPair->second);
217 gurobiConstraint.coefficients.push_back(variableCoefficientPair.second);
221 switch (relationType) {
223 gurobiConstraint.sense = GRB_LESS_EQUAL;
224 gurobiConstraint.rhs -= integerTolerance;
227 gurobiConstraint.sense = GRB_LESS_EQUAL;
230 gurobiConstraint.sense = GRB_GREATER_EQUAL;
231 gurobiConstraint.rhs += integerTolerance;
234 gurobiConstraint.sense = GRB_GREATER_EQUAL;
237 gurobiConstraint.sense = GRB_EQUAL;
242 return gurobiConstraint;
245template<
typename ValueType,
bool RawMode>
247 if constexpr (!RawMode) {
248 STORM_LOG_TRACE(
"Adding constraint " << name <<
" to GurobiLpSolver:\n"
249 <<
"\t" << constraint);
250 STORM_LOG_ASSERT(constraint.getManager() == this->getManager(),
"Constraint was not built over the proper variables.");
254 auto grbConstr = createConstraint<ValueType, RawMode>(constraint, this->variableToIndexMap, environment->getIntegerTolerance());
255 int error = GRBaddconstr(model, grbConstr.variableIndices.size(), grbConstr.variableIndices.data(), grbConstr.coefficients.data(), grbConstr.sense,
256 grbConstr.rhs, name ==
"" ?
nullptr : name.c_str());
258 "Could not assert constraint (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
261template<
typename ValueType,
bool RawMode>
263 Constraint
const& constraint) {
266 if constexpr (RawMode) {
267 indVar = indicatorVariable;
269 STORM_LOG_ASSERT(this->variableToIndexMap.count(indicatorVariable) > 0,
"Indicator Variable " << indicatorVariable.getName() <<
" unknown to solver.");
270 STORM_LOG_ASSERT(indicatorVariable.hasIntegerType(),
"Indicator Variable " << indicatorVariable.getName() <<
" has unexpected type.");
271 STORM_LOG_ASSERT(constraint.getManager() == this->getManager(),
"Constraint was not built over the proper variables.");
272 STORM_LOG_TRACE(
"Adding Indicator constraint " << name <<
" to GurobiLpSolver:\n"
273 <<
"\t(" << indicatorVariable.getName() <<
"==" << indicatorValue <<
") implies " << constraint);
274 indVar = this->variableToIndexMap.at(indicatorVariable);
276 int indVal = indicatorValue ? 1 : 0;
277 auto grbConstr = createConstraint<ValueType, RawMode>(constraint, this->variableToIndexMap, environment->getIntegerTolerance());
279 int error = GRBaddgenconstrIndicator(model, name ==
"" ?
nullptr : name.c_str(), indVar, indVal, grbConstr.variableIndices.size(),
280 grbConstr.variableIndices.data(), grbConstr.coefficients.data(), grbConstr.sense, grbConstr.rhs);
282 "Could not assert constraint (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
285template<
typename ValueType,
bool RawMode>
291 int error = GRBsetintattr(model,
"ModelSense", this->getOptimizationDirection() == OptimizationDirection::Minimize ? 1 : -1);
293 "Unable to set Gurobi model sense (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
296 error = GRBoptimize(model);
298 "Unable to optimize Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
300 this->currentModelHasBeenOptimized =
true;
303template<
typename ValueType,
bool RawMode>
305 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidStateException,
306 "Illegal call to GurobiLpSolver<ValueType, RawMode>::isInfeasible: model has not been optimized.");
308 int optimalityStatus = 0;
310 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
312 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
316 if (optimalityStatus == GRB_INF_OR_UNBD) {
317 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0);
319 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
323 error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
325 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
327 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1);
329 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
332 return optimalityStatus == GRB_INFEASIBLE;
335template<
typename ValueType,
bool RawMode>
337 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidStateException,
338 "Illegal call to GurobiLpSolver<ValueType, RawMode>::isUnbounded: model has not been optimized.");
340 int optimalityStatus = 0;
342 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
344 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
348 if (optimalityStatus == GRB_INF_OR_UNBD) {
349 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0);
351 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
355 error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
357 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
359 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1);
361 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
364 return optimalityStatus == GRB_UNBOUNDED;
367template<
typename ValueType,
bool RawMode>
369 if (!this->currentModelHasBeenOptimized) {
372 int optimalityStatus = 0;
374 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
376 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
378 return optimalityStatus == GRB_OPTIMAL;
381template<
typename ValueType,
bool RawMode>
383 if (!this->isOptimal()) {
384 STORM_LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException,
385 "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(**environment) <<
").");
386 STORM_LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException,
387 "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(**environment) <<
").");
389 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
393 if constexpr (RawMode) {
396 STORM_LOG_ASSERT(variableToIndexMap.count(variable) != 0,
"Accessing value of unknown variable '" << variable.getName() <<
"'.");
397 varIndex = variableToIndexMap.at(variable);
401 int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, varIndex, &value);
403 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
408template<
typename ValueType,
bool RawMode>
410 if (!this->isOptimal()) {
411 STORM_LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException,
412 "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(**environment) <<
").");
413 STORM_LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException,
414 "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(**environment) <<
").");
416 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
420 if constexpr (RawMode) {
423 STORM_LOG_ASSERT(variableToIndexMap.count(variable) != 0,
"Accessing value of unknown variable '" << variable.getName() <<
"'.");
424 varIndex = variableToIndexMap.at(variable);
428 int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, varIndex, &value);
430 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
431 double roundedValue = std::round(value);
432 double diff = std::abs(roundedValue - value);
434 "Illegal value for integer variable in Gurobi solution (" << value <<
"). Difference to nearest int is " << diff);
435 return static_cast<int_fast64_t
>(roundedValue);
438template<
typename ValueType,
bool RawMode>
440 if (!this->isOptimal()) {
441 STORM_LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException,
442 "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(**environment) <<
").");
443 STORM_LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException,
444 "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(**environment) <<
").");
446 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
450 if constexpr (RawMode) {
453 STORM_LOG_ASSERT(variableToIndexMap.count(variable) != 0,
"Accessing value of unknown variable '" << variable.getName() <<
"'.");
454 varIndex = variableToIndexMap.at(variable);
458 int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, varIndex, &value);
460 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
464 "Illegal value for binary variable in Gurobi solution (" << value <<
").");
467 STORM_LOG_ERROR_COND(std::abs(value) <= environment->getIntegerTolerance(),
"Illegal value for binary variable in Gurobi solution (" << value <<
").");
472template<
typename ValueType,
bool RawMode>
474 if (!this->isOptimal()) {
475 STORM_LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException,
476 "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(**environment) <<
").");
477 STORM_LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException,
478 "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(**environment) <<
").");
480 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
484 int error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &value);
486 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
491template<
typename ValueType,
bool RawMode>
493 int error = GRBwrite(model, filename.c_str());
495 "Unable to write Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
") to file.");
498template<
typename ValueType,
bool RawMode>
500 IncrementalLevel lvl;
502 GRBgetintattr(model, GRB_INT_ATTR_NUMCONSTRS, &num);
503 lvl.firstConstraintIndex = num;
504 GRBgetintattr(model, GRB_INT_ATTR_NUMGENCONSTRS, &num);
505 lvl.firstGenConstraintIndex = num;
506 incrementalData.push_back(lvl);
509template<
typename ValueType,
bool RawMode>
511 if (incrementalData.empty()) {
514 IncrementalLevel
const& lvl = incrementalData.back();
516 GRBgetintattr(model, GRB_INT_ATTR_NUMCONSTRS, &num);
518 int error = GRBdelconstrs(model, indicesToBeRemoved.size(), indicesToBeRemoved.data());
520 "Unable to delete constraints (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
521 GRBgetintattr(model, GRB_INT_ATTR_NUMGENCONSTRS, &num);
524 "Unable to delete general constraints (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
525 indicesToBeRemoved.clear();
527 if (!lvl.variables.empty()) {
530 for (
auto const& var : lvl.variables) {
532 auto it = variableToIndexMap.find(var);
533 firstIndex = it->second;
534 variableToIndexMap.erase(it);
537 variableToIndexMap.erase(var);
541 error = GRBdelvars(model, indicesToBeRemoved.size(), indicesToBeRemoved.data());
543 "Unable to delete variables (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
544 nextVariableIndex = firstIndex;
548 GRBgetintattr(model, GRB_INT_ATTR_NUMCONSTRS, &num);
549 STORM_LOG_THROW(lvl.firstConstraintIndex == num, storm::exceptions::InvalidStateException,
"Unexpected number of constraints after deletion.");
550 GRBgetintattr(model, GRB_INT_ATTR_NUMGENCONSTRS, &num);
551 STORM_LOG_THROW(lvl.firstGenConstraintIndex == num, storm::exceptions::InvalidStateException,
552 "Unexpected number of general constraints after deletion.");
553 GRBgetintattr(model, GRB_INT_ATTR_NUMVARS, &num);
554 STORM_LOG_THROW(nextVariableIndex == num, storm::exceptions::InvalidStateException,
"Unexpected number ofvariables after deletion.");
556 incrementalData.pop_back();
560template<
typename ValueType,
bool RawMode>
562 int error = GRBsetintparam(GRBgetenv(model),
"PoolSolutions", value);
564 "Unable to set Gurobi Parameter PoolSolutions (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
567template<
typename ValueType,
bool RawMode>
569 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidStateException,
570 "Illegal call to GurobiLpSolver<ValueType, RawMode>::getSolutionCount: model has not been optimized.");
572 int error = GRBgetintattr(model,
"SolCount", &result);
573 STORM_LOG_THROW(error == 0 && result >= 0, storm::exceptions::InvalidStateException,
"Unable to get solution count or invalid number of solutions.");
577template<
typename ValueType,
bool RawMode>
579 if (!this->isOptimal()) {
580 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidAccessException,
581 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
583 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(),
"Invalid solution index.");
586 if constexpr (RawMode) {
589 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
590 "Accessing value of unknown variable '" << variable.getName() <<
"'.");
591 varIndex = variableToIndexMap.at(variable);
595 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
597 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
598 error = GRBgetdblattrelement(model, GRB_DBL_ATTR_Xn, varIndex, &value);
600 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
605template<
typename ValueType,
bool RawMode>
607 if (!this->isOptimal()) {
608 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidAccessException,
609 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
611 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(),
"Invalid solution index.");
614 if constexpr (RawMode) {
617 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
618 "Accessing value of unknown variable '" << variable.getName() <<
"'.");
619 varIndex = variableToIndexMap.at(variable);
623 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
625 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
626 error = GRBgetdblattrelement(model, GRB_DBL_ATTR_Xn, varIndex, &value);
628 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
629 double roundedValue = std::round(value);
630 double diff = std::abs(roundedValue - value);
632 "Illegal value for integer variable in Gurobi solution (" << value <<
"). Difference to nearest int is " << diff);
633 return static_cast<int_fast64_t
>(roundedValue);
636template<
typename ValueType,
bool RawMode>
638 if (!this->isOptimal()) {
639 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidAccessException,
640 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
642 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(),
"Invalid solution index.");
645 if constexpr (RawMode) {
648 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
649 "Accessing value of unknown variable '" << variable.getName() <<
"'.");
650 varIndex = variableToIndexMap.at(variable);
654 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
656 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
657 error = GRBgetdblattrelement(model, GRB_DBL_ATTR_Xn, varIndex, &value);
659 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
663 "Illegal value for integer variable in Gurobi solution (" << value <<
").");
666 STORM_LOG_ERROR_COND(std::abs(value) <= environment->getIntegerTolerance(),
"Illegal value for integer variable in Gurobi solution (" << value <<
").");
671template<
typename ValueType,
bool RawMode>
673 if (!this->isOptimal()) {
674 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidAccessException,
675 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) <<
").");
677 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(),
"Invalid solution index.");
680 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
682 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
683 error = GRBgetdblattr(model, GRB_DBL_ATTR_POOLOBJVAL, &value);
685 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
690template<
typename ValueType,
bool RawMode>
699 "Unable to set Gurobi MILP GAP (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
702template<
typename ValueType,
bool RawMode>
705 int error = GRBgetdblattr(model, GRB_DBL_ATTR_MIPGAP, &relativeGap);
707 "Unable to get Gurobi MILP GAP (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
716template<
typename ValueType,
bool RawMode>
718 int error = GRBsetdblparam(GRBgetenv(model), GRB_DBL_PAR_TIMELIMIT, seconds);
719 timeLimit.emplace(seconds);
721 "Unable to set Gurobi time limit (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
724template<
typename ValueType,
bool RawMode>
726 STORM_LOG_THROW(timeLimit.has_value(), storm::exceptions::InvalidAccessException,
"Unable to get Gurobi time limit because none was specified.");
727 return timeLimit.value();
730template<
typename ValueType,
bool RawMode>
732 return timeLimit.has_value();
735template<
typename ValueType,
bool RawMode>
737 if (!this->currentModelHasBeenOptimized) {
742 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &status);
744 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) <<
", error code " << error <<
").");
746 return status == GRB_TIME_LIMIT;
750template<
typename ValueType,
bool RawMode>
753 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
754 "version of support with Gurobi support.");
757template<
typename ValueType,
bool RawMode>
760 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
761 "version of support with Gurobi support.");
764template<
typename ValueType,
bool RawMode>
767 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
768 "version of support with Gurobi support.");
771template<
typename ValueType,
bool RawMode>
774 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
775 "version of support with Gurobi support.");
778template<
typename ValueType,
bool RawMode>
781template<
typename ValueType,
bool RawMode>
783 std::optional<ValueType>
const&,
784 std::optional<ValueType>
const&, ValueType) {
786 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
787 "version of support with Gurobi support.");
790template<
typename ValueType,
bool RawMode>
793 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
794 "version of support with Gurobi support.");
797template<
typename ValueType,
bool RawMode>
800 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
801 "version of support with Gurobi support.");
804template<
typename ValueType,
bool RawMode>
807 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
808 "version of support with Gurobi support.");
811template<
typename ValueType,
bool RawMode>
814 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
815 "version of support with Gurobi support.");
818template<
typename ValueType,
bool RawMode>
821 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
822 "version of support with Gurobi support.");
825template<
typename ValueType,
bool RawMode>
828 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
829 "version of support with Gurobi support.");
832template<
typename ValueType,
bool RawMode>
835 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
836 "version of support with Gurobi support.");
839template<
typename ValueType,
bool RawMode>
842 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
843 "version of support with Gurobi support.");
846template<
typename ValueType,
bool RawMode>
849 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
850 "version of support with Gurobi support.");
853template<
typename ValueType,
bool RawMode>
856 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
857 "version of support with Gurobi support.");
860template<
typename ValueType,
bool RawMode>
863 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
864 "version of support with Gurobi support.");
867template<
typename ValueType,
bool RawMode>
870 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
871 "version of support with Gurobi support.");
874template<
typename ValueType,
bool RawMode>
877 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
878 "version of support with Gurobi support.");
881template<
typename ValueType,
bool RawMode>
884 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
885 "version of support with Gurobi support.");
888template<
typename ValueType,
bool RawMode>
891 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
892 "version of storm with Gurobi support.");
895template<
typename ValueType,
bool RawMode>
898 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
899 "version of storm with Gurobi support.");
902template<
typename ValueType,
bool RawMode>
905 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
906 "version of storm with Gurobi support.");
909template<
typename ValueType,
bool RawMode>
912 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
913 "version of storm with Gurobi support.");
916template<
typename ValueType,
bool RawMode>
919 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
920 "version of storm with Gurobi support.");
923template<
typename ValueType,
bool RawMode>
926 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
927 "version of storm with Gurobi support.");
930template<
typename ValueType,
bool RawMode>
933 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
934 "version of storm with Gurobi support.");
937template<
typename ValueType,
bool RawMode>
940 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
941 "version of storm with Gurobi support.");
944template<
typename ValueType,
bool RawMode>
947 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
948 "version of storm with Gurobi support.");
951template<
typename ValueType,
bool RawMode>
954 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
955 "version of storm with Gurobi support.");
958template<
typename ValueType,
bool RawMode>
961 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
962 "version of storm with Gurobi support.");
965template<
typename ValueType,
bool RawMode>
968 "This version of storm was compiled without support for Gurobi. Yet, a method was called that requires this support. Please choose a "
969 "version of storm with Gurobi support.");
979 return "primal-simplex";
981 return "dual-simplex";
987 return "deterministic-concurrent";
989 return "deterministic-concurrent-simplex";
991 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Unknown solver method.");
1008template class GurobiLpSolver<double, true>;
1009template class GurobiLpSolver<double, false>;
1010template class GurobiLpSolver<storm::RationalNumber, true>;
1011template class GurobiLpSolver<storm::RationalNumber, false>;
double getIntegerTolerance() const
uint64_t getNumberOfConcurrentMipThreads() const
uint64_t getMIPFocus() const
uint64_t getNumberOfThreads() const
storm::solver::GurobiSolverMethod const & getMethod() const
double getIntegerTolerance() const
void setOutput(bool set=false)
void initialize(storm::GurobiSolverEnvironment const &gurobiSettings, bool debug)
Sets some properties of the Gurobi environment according to parameters given by the options.
virtual ~GurobiEnvironment()
A class that implements the LpSolver interface using Gurobi.
virtual ~GurobiLpSolver()
Destructs a solver by freeing the pointers to Gurobi's structures.
virtual bool isInfeasible() const override
Retrieves whether the model was found to be infeasible.
virtual int_fast64_t getIntegerValue(Variable const &name) const override
Retrieves the value of the integer variable with the given name.
virtual bool isUnbounded() const override
Retrieves whether the model was found to be infeasible.
virtual void setMaximalMILPGap(ValueType const &gap, bool relative) override
Specifies the maximum difference between lower- and upper objective bounds that triggers termination.
virtual void push() override
Pushes a backtracking point on the solver's stack.
void setMaximalSolutionCount(uint64_t value)
typename LpSolver< ValueType, RawMode >::VariableType VariableType
GurobiLpSolver(std::shared_ptr< GurobiEnvironment > const &environment, std::string const &name, OptimizationDirection const &optDir)
Constructs a solver with the given name and model sense.
virtual void addIndicatorConstraint(std::string const &name, Variable indicatorVariable, bool indicatorValue, Constraint const &constraint) override
Adds the given indicator constraint to the LP problem: "If indicatorVariable == indicatorValue,...
virtual void addConstraint(std::string const &name, Constraint const &constraint) override
Adds a the given constraint to the LP problem.
virtual ValueType getContinuousValue(Variable const &name) const override
Retrieves the value of the continuous variable with the given name.
virtual bool getBinaryValue(Variable const &name) const override
Retrieves the value of the binary variable with the given name.
virtual ValueType getObjectiveValue() const override
Retrieves the value of the objective function.
void setTimeLimit(uint64_t seconds)
virtual void pop() override
Pops a backtracking point from the solver's stack.
virtual void writeModelToFile(std::string const &filename) const override
Writes the current LP problem to the given file.
typename LpSolver< ValueType, RawMode >::Variable Variable
virtual void optimize() const override
Optimizes the LP problem previously constructed.
virtual Variable addVariable(std::string const &name, VariableType const &type, std::optional< ValueType > const &lowerBound=std::nullopt, std::optional< ValueType > const &upperBound=std::nullopt, ValueType objectiveFunctionCoefficient=0) override
uint64_t getSolutionCount() const
typename LpSolver< ValueType, RawMode >::Constraint Constraint
virtual ValueType getMILPGap(bool relative) const override
Returns the obtained gap after a call to optimize().
virtual bool isOptimal() const override
Retrieves whether the model was found to be optimal, i.e.
virtual void update() const override
Updates the model to make the variables that have been declared since the last call to update usable.
An interface that captures the functionality of an LP solver.
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_ERROR_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
RelationType
An enum type specifying the different relations applicable.
std::string toString(GurobiSolverMethod const &method)
Yields a string representation of the GurobiSolverMethod.
std::optional< GurobiSolverMethod > gurobiSolverMethodFromString(std::string const &method)
std::vector< GurobiSolverMethod > getGurobiSolverMethods()
std::vector< T > buildVectorForRange(T min, T max)
Constructs a vector [min, min+1, ...., max-1].
ValueType abs(ValueType const &number)
TargetType convertNumber(SourceType const &number)
solver::OptimizationDirection OptimizationDirection
std::map< storm::expressions::Variable, double >::const_iterator end() const
void separateVariablesFromConstantPart(VariableCoefficients &rhs)
Brings all variables of the right-hand side coefficients to the left-hand side by negating them and m...
std::map< storm::expressions::Variable, double >::const_iterator begin() const
double getConstantPart() const