Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
GurobiLpSolver.cpp
Go to the documentation of this file.
2
3#include <numeric>
4
18
19namespace storm {
20namespace solver {
21
23#ifdef STORM_HAVE_GUROBI
24 if (initialized) {
25 GRBfreeenv(env);
26 }
27#endif
28}
29
30#ifdef STORM_HAVE_GUROBI
31GRBenv* GurobiEnvironment::operator*() {
32 STORM_LOG_ASSERT(initialized, "Gurobi Environment has not been initialized.");
33 return env;
34}
35#endif
36
37void GurobiEnvironment::initialize(storm::GurobiSolverEnvironment const& gurobiSettings, bool debug) {
38 integerTolerance = gurobiSettings.getIntegerTolerance();
39#ifdef STORM_HAVE_GUROBI
40 // Create the environment.
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 << ").");
45 STORM_LOG_THROW(false, storm::exceptions::InvalidStateException,
46 "Could not initialize Gurobi environment (" << GRBgeterrormsg(env) << ", error code " << error << ").");
47 }
48 setOutput(debug || gurobiSettings.isOutputSet());
49
50 error = GRBsetintparam(env, "Method", static_cast<int>(gurobiSettings.getMethod()));
51 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
52 "Unable to set Gurobi Parameter Method (" << GRBgeterrormsg(env) << ", error code " << error << ").");
53
54 // Enable the following line to restrict Gurobi to one thread only.
55 error = GRBsetintparam(env, "Threads", gurobiSettings.getNumberOfThreads());
56 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
57 "Unable to set Gurobi Parameter Threads (" << GRBgeterrormsg(env) << ", error code " << error << ").");
58
59 error = GRBsetintparam(env, "MIPFocus", gurobiSettings.getMIPFocus());
60 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
61 "Unable to set Gurobi Parameter MIPFocus (" << GRBgeterrormsg(env) << ", error code " << error << ").");
62
63 error = GRBsetintparam(env, "ConcurrentMIP", gurobiSettings.getNumberOfConcurrentMipThreads());
64 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
65 "Unable to set Gurobi Parameter ConcurrentMIP (" << GRBgeterrormsg(env) << ", error code " << error << ").");
66
67 // Enable the following line to force Gurobi to be as precise about the binary variables as required by the given precision option.
68 error = GRBsetdblparam(env, "IntFeasTol", gurobiSettings.getIntegerTolerance());
69 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
70 "Unable to set Gurobi Parameter IntFeasTol (" << GRBgeterrormsg(env) << ", error code " << error << ").");
71#endif
72 initialized = true;
73}
74
76 return integerTolerance;
77}
78
80#ifdef STORM_HAVE_GUROBI
81 int error = GRBsetintparam(env, "OutputFlag", set);
82 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
83 "Unable to set Gurobi Parameter OutputFlag (" << GRBgeterrormsg(env) << ", error code " << error << ").");
84#else
85 (void)set;
86#endif
87}
88
89#ifdef STORM_HAVE_GUROBI
90
91template<typename ValueType, bool RawMode>
92GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const& environment, std::string const& name,
93 OptimizationDirection const& optDir)
94 : LpSolver<ValueType, RawMode>(optDir), model(nullptr), environment(environment), nextVariableIndex(0) {
95 // Create the model.
96 int error = 0;
97 error = GRBnewmodel(**environment, &model, name.c_str(), 0, nullptr, nullptr, nullptr, nullptr, nullptr);
98 STORM_LOG_THROW(!error, storm::exceptions::InvalidStateException,
99 "Could not initialize Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
100}
101
102template<typename ValueType, bool RawMode>
103GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const& environment, std::string const& name)
104 : GurobiLpSolver(environment, name, OptimizationDirection::Minimize) {
105 // Intentionally left empty.
106}
107
108template<typename ValueType, bool RawMode>
109GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const& environment, OptimizationDirection const& optDir)
110 : GurobiLpSolver(environment, "", optDir) {
111 // Intentionally left empty.
112}
113
114template<typename ValueType, bool RawMode>
115GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const& environment)
116 : GurobiLpSolver(environment, "", OptimizationDirection::Minimize) {
117 // Intentionally left empty.
118}
119
120template<typename ValueType, bool RawMode>
122 // Dispose of the objects allocated inside Gurobi.
123 GRBfreemodel(model);
124}
125
126template<typename ValueType, bool RawMode>
128 int error = GRBupdatemodel(model);
129 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
130 "Unable to update Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
131
132 // Since the model changed, we erase the optimality flag.
133 this->currentModelHasBeenOptimized = false;
134}
135
136template<typename ValueType, bool RawMode>
137char getGurobiType(typename GurobiLpSolver<ValueType, RawMode>::VariableType const& type) {
138 switch (type) {
140 return GRB_CONTINUOUS;
142 return GRB_INTEGER;
144 return GRB_BINARY;
145 }
146 STORM_LOG_ASSERT(false, "Unexpected variable type.");
147 return -1;
148}
149
150template<typename ValueType, bool RawMode>
151typename GurobiLpSolver<ValueType, RawMode>::Variable GurobiLpSolver<ValueType, RawMode>::addVariable(std::string const& name, VariableType const& type,
152 std::optional<ValueType> const& lowerBound,
153 std::optional<ValueType> const& upperBound,
154 ValueType objectiveFunctionCoefficient) {
155 Variable resultVar;
156 if constexpr (RawMode) {
157 resultVar = nextVariableIndex;
158 } else {
159 resultVar = this->declareOrGetExpressionVariable(name, type);
160 // Assert whether the variable does not exist yet.
161 // Due to incremental usage (push(), pop()), a variable might be declared in the manager but not in the lp model.
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);
166 }
167 }
168 ++nextVariableIndex;
169
170 // Create the actual variable.
171 int error = 0;
172 error = GRBaddvar(model, 0, nullptr, nullptr, storm::utility::convertNumber<double>(objectiveFunctionCoefficient),
173 lowerBound.has_value() ? storm::utility::convertNumber<double>(*lowerBound) : -GRB_INFINITY,
174 upperBound.has_value() ? storm::utility::convertNumber<double>(*upperBound) : GRB_INFINITY, getGurobiType<ValueType, RawMode>(type),
175 name.c_str());
176 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
177 "Could not create binary Gurobi variable (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
178 return resultVar;
179}
180
181struct GurobiConstraint {
182 std::vector<int> variableIndices;
183 std::vector<double> coefficients;
184 char sense;
185 double rhs;
186};
187
188template<typename ValueType, bool RawMode>
189GurobiConstraint createConstraint(typename GurobiLpSolver<ValueType, RawMode>::Constraint const& constraint,
190 std::map<storm::expressions::Variable, int> const& variableToIndexMap, double integerTolerance) {
191 GurobiConstraint gurobiConstraint;
193 if constexpr (RawMode) {
194 gurobiConstraint.rhs = storm::utility::convertNumber<double>(constraint.rhs);
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) {
200 gurobiConstraint.coefficients.push_back(storm::utility::convertNumber<double>(coef));
201 }
202 } else {
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));
208 leftCoefficients.separateVariablesFromConstantPart(rightCoefficients);
209 gurobiConstraint.rhs = rightCoefficients.getConstantPart();
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);
218 }
219 }
220 // Determine the type of the constraint and add it properly.
221 switch (relationType) {
223 gurobiConstraint.sense = GRB_LESS_EQUAL;
224 gurobiConstraint.rhs -= integerTolerance;
225 break;
227 gurobiConstraint.sense = GRB_LESS_EQUAL;
228 break;
230 gurobiConstraint.sense = GRB_GREATER_EQUAL;
231 gurobiConstraint.rhs += integerTolerance;
232 break;
234 gurobiConstraint.sense = GRB_GREATER_EQUAL;
235 break;
237 gurobiConstraint.sense = GRB_EQUAL;
238 break;
239 default:
240 STORM_LOG_ASSERT(false, "Illegal operator in LP solver constraint.");
241 }
242 return gurobiConstraint;
243}
244
245template<typename ValueType, bool RawMode>
246void GurobiLpSolver<ValueType, RawMode>::addConstraint(std::string const& name, Constraint const& constraint) {
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.");
251 }
252
253 // Extract constraint data
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());
257 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
258 "Could not assert constraint (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
259}
260
261template<typename ValueType, bool RawMode>
262void GurobiLpSolver<ValueType, RawMode>::addIndicatorConstraint(std::string const& name, Variable indicatorVariable, bool indicatorValue,
263 Constraint const& constraint) {
264 int indVar;
265 // Extract constraint data
266 if constexpr (RawMode) {
267 indVar = indicatorVariable;
268 } else {
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);
275 }
276 int indVal = indicatorValue ? 1 : 0;
277 auto grbConstr = createConstraint<ValueType, RawMode>(constraint, this->variableToIndexMap, environment->getIntegerTolerance());
278 // Gurobi considers indicator constraints as a certain kind of what they call "general constraints".
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);
281 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
282 "Could not assert constraint (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
283}
284
285template<typename ValueType, bool RawMode>
287 // First incorporate all recent changes.
288 this->update();
289
290 // Set the most recently set model sense.
291 int error = GRBsetintattr(model, "ModelSense", this->getOptimizationDirection() == OptimizationDirection::Minimize ? 1 : -1);
292 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
293 "Unable to set Gurobi model sense (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
294
295 // Then we actually optimize the model.
296 error = GRBoptimize(model);
297 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
298 "Unable to optimize Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
299
300 this->currentModelHasBeenOptimized = true;
301}
302
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.");
307
308 int optimalityStatus = 0;
309
310 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
311 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
312 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
313
314 // By default, Gurobi may tell us only that the model is either infeasible or unbounded. To decide which one
315 // it is, we need to perform an extra step.
316 if (optimalityStatus == GRB_INF_OR_UNBD) {
317 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0);
318 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
319 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
320
321 this->optimize();
322
323 error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
324 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
325 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
326
327 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1);
328 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
329 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
330 }
331
332 return optimalityStatus == GRB_INFEASIBLE;
333}
334
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.");
339
340 int optimalityStatus = 0;
341
342 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
343 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
344 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
345
346 // By default, Gurobi may tell us only that the model is either infeasible or unbounded. To decide which one
347 // it is, we need to perform an extra step.
348 if (optimalityStatus == GRB_INF_OR_UNBD) {
349 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0);
350 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
351 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
352
353 this->optimize();
354
355 error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
356 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
357 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
358
359 error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1);
360 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
361 "Unable to set Gurobi parameter (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
362 }
363
364 return optimalityStatus == GRB_UNBOUNDED;
365}
366
367template<typename ValueType, bool RawMode>
369 if (!this->currentModelHasBeenOptimized) {
370 return false;
371 }
372 int optimalityStatus = 0;
373
374 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus);
375 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
376 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
377
378 return optimalityStatus == GRB_OPTIMAL;
379}
380
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) << ").");
388 STORM_LOG_THROW(false, storm::exceptions::InvalidAccessException,
389 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) << ").");
390 }
391
392 int varIndex;
393 if constexpr (RawMode) {
394 varIndex = variable;
395 } else {
396 STORM_LOG_ASSERT(variableToIndexMap.count(variable) != 0, "Accessing value of unknown variable '" << variable.getName() << "'.");
397 varIndex = variableToIndexMap.at(variable);
398 }
399
400 double value = 0;
401 int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, varIndex, &value);
402 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
403 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
404
406}
407
408template<typename ValueType, bool RawMode>
409int_fast64_t GurobiLpSolver<ValueType, RawMode>::getIntegerValue(Variable const& variable) const {
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) << ").");
415 STORM_LOG_THROW(false, storm::exceptions::InvalidAccessException,
416 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) << ").");
417 }
418
419 int varIndex;
420 if constexpr (RawMode) {
421 varIndex = variable;
422 } else {
423 STORM_LOG_ASSERT(variableToIndexMap.count(variable) != 0, "Accessing value of unknown variable '" << variable.getName() << "'.");
424 varIndex = variableToIndexMap.at(variable);
425 }
426
427 double value = 0;
428 int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, varIndex, &value);
429 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
430 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
431 double roundedValue = std::round(value);
432 double diff = std::abs(roundedValue - value);
433 STORM_LOG_ERROR_COND(diff <= environment->getIntegerTolerance(),
434 "Illegal value for integer variable in Gurobi solution (" << value << "). Difference to nearest int is " << diff);
435 return static_cast<int_fast64_t>(roundedValue);
436}
437
438template<typename ValueType, bool RawMode>
439bool GurobiLpSolver<ValueType, RawMode>::getBinaryValue(Variable const& variable) const {
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) << ").");
445 STORM_LOG_THROW(false, storm::exceptions::InvalidAccessException,
446 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) << ").");
447 }
448
449 int varIndex;
450 if constexpr (RawMode) {
451 varIndex = variable;
452 } else {
453 STORM_LOG_ASSERT(variableToIndexMap.count(variable) != 0, "Accessing value of unknown variable '" << variable.getName() << "'.");
454 varIndex = variableToIndexMap.at(variable);
455 }
456
457 double value = 0;
458 int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, varIndex, &value);
459 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
460 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
461
462 if (value > 0.5) {
463 STORM_LOG_ERROR_COND(std::abs(value - 1.0) <= environment->getIntegerTolerance(),
464 "Illegal value for binary variable in Gurobi solution (" << value << ").");
465 return true;
466 } else {
467 STORM_LOG_ERROR_COND(std::abs(value) <= environment->getIntegerTolerance(), "Illegal value for binary variable in Gurobi solution (" << value << ").");
468 return false;
469 }
470}
471
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) << ").");
479 STORM_LOG_THROW(false, storm::exceptions::InvalidAccessException,
480 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) << ").");
481 }
482
483 double value = 0;
484 int error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &value);
485 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
486 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
487
489}
490
491template<typename ValueType, bool RawMode>
492void GurobiLpSolver<ValueType, RawMode>::writeModelToFile(std::string const& filename) const {
493 int error = GRBwrite(model, filename.c_str());
494 STORM_LOG_THROW(!error, storm::exceptions::InvalidStateException,
495 "Unable to write Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ") to file.");
496}
497
498template<typename ValueType, bool RawMode>
500 IncrementalLevel lvl;
501 int num;
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);
507}
508
509template<typename ValueType, bool RawMode>
511 if (incrementalData.empty()) {
512 STORM_LOG_ERROR("Tried to pop from a solver without pushing before.");
513 } else {
514 IncrementalLevel const& lvl = incrementalData.back();
515 int num;
516 GRBgetintattr(model, GRB_INT_ATTR_NUMCONSTRS, &num);
517 std::vector<int> indicesToBeRemoved = storm::utility::vector::buildVectorForRange(lvl.firstConstraintIndex, num);
518 int error = GRBdelconstrs(model, indicesToBeRemoved.size(), indicesToBeRemoved.data());
519 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
520 "Unable to delete constraints (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
521 GRBgetintattr(model, GRB_INT_ATTR_NUMGENCONSTRS, &num);
522 indicesToBeRemoved = storm::utility::vector::buildVectorForRange(lvl.firstGenConstraintIndex, num);
523 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
524 "Unable to delete general constraints (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
525 indicesToBeRemoved.clear();
526
527 if (!lvl.variables.empty()) {
528 int firstIndex = -1;
529 bool first = true;
530 for (auto const& var : lvl.variables) {
531 if (first) {
532 auto it = variableToIndexMap.find(var);
533 firstIndex = it->second;
534 variableToIndexMap.erase(it);
535 first = false;
536 } else {
537 variableToIndexMap.erase(var);
538 }
539 }
540 std::vector<int> indicesToBeRemoved = storm::utility::vector::buildVectorForRange(firstIndex, nextVariableIndex);
541 error = GRBdelvars(model, indicesToBeRemoved.size(), indicesToBeRemoved.data());
542 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
543 "Unable to delete variables (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
544 nextVariableIndex = firstIndex;
545 }
546 update();
547 // Assert that indices are as expected
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.");
555
556 incrementalData.pop_back();
557 }
558}
559
560template<typename ValueType, bool RawMode>
562 int error = GRBsetintparam(GRBgetenv(model), "PoolSolutions", value);
563 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
564 "Unable to set Gurobi Parameter PoolSolutions (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
565}
566
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.");
571 int result = -1;
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.");
574 return result;
575}
576
577template<typename ValueType, bool RawMode>
578ValueType GurobiLpSolver<ValueType, RawMode>::getContinuousValue(Variable const& variable, uint64_t const& solutionIndex) const {
579 if (!this->isOptimal()) {
580 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidAccessException,
581 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) << ").");
582 }
583 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(), "Invalid solution index.");
584
585 int varIndex;
586 if constexpr (RawMode) {
587 varIndex = variable;
588 } else {
589 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
590 "Accessing value of unknown variable '" << variable.getName() << "'.");
591 varIndex = variableToIndexMap.at(variable);
592 }
593
594 double value = 0;
595 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
596 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
597 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
598 error = GRBgetdblattrelement(model, GRB_DBL_ATTR_Xn, varIndex, &value);
599 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
600 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
601
603}
604
605template<typename ValueType, bool RawMode>
606int_fast64_t GurobiLpSolver<ValueType, RawMode>::getIntegerValue(Variable const& variable, uint64_t const& solutionIndex) const {
607 if (!this->isOptimal()) {
608 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidAccessException,
609 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) << ").");
610 }
611 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(), "Invalid solution index.");
612
613 int varIndex;
614 if constexpr (RawMode) {
615 varIndex = variable;
616 } else {
617 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
618 "Accessing value of unknown variable '" << variable.getName() << "'.");
619 varIndex = variableToIndexMap.at(variable);
620 }
621
622 double value = 0;
623 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
624 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
625 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
626 error = GRBgetdblattrelement(model, GRB_DBL_ATTR_Xn, varIndex, &value);
627 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
628 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
629 double roundedValue = std::round(value);
630 double diff = std::abs(roundedValue - value);
631 STORM_LOG_ERROR_COND(diff <= environment->getIntegerTolerance(),
632 "Illegal value for integer variable in Gurobi solution (" << value << "). Difference to nearest int is " << diff);
633 return static_cast<int_fast64_t>(roundedValue);
634}
635
636template<typename ValueType, bool RawMode>
637bool GurobiLpSolver<ValueType, RawMode>::getBinaryValue(Variable const& variable, uint64_t const& solutionIndex) const {
638 if (!this->isOptimal()) {
639 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidAccessException,
640 "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(**environment) << ").");
641 }
642 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(), "Invalid solution index.");
643
644 int varIndex;
645 if constexpr (RawMode) {
646 varIndex = variable;
647 } else {
648 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
649 "Accessing value of unknown variable '" << variable.getName() << "'.");
650 varIndex = variableToIndexMap.at(variable);
651 }
652
653 double value = 0;
654 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
655 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
656 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
657 error = GRBgetdblattrelement(model, GRB_DBL_ATTR_Xn, varIndex, &value);
658 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
659 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
660
661 if (value > 0.5) {
662 STORM_LOG_ERROR_COND(std::abs(value - 1) <= environment->getIntegerTolerance(),
663 "Illegal value for integer variable in Gurobi solution (" << value << ").");
664 return true;
665 } else {
666 STORM_LOG_ERROR_COND(std::abs(value) <= environment->getIntegerTolerance(), "Illegal value for integer variable in Gurobi solution (" << value << ").");
667 return false;
668 }
669}
670
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) << ").");
676 }
677 STORM_LOG_ASSERT(solutionIndex < getSolutionCount(), "Invalid solution index.");
678
679 double value = 0;
680 int error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_SOLUTIONNUMBER, solutionIndex);
681 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
682 "Unable to set Gurobi solution index (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
683 error = GRBgetdblattr(model, GRB_DBL_ATTR_POOLOBJVAL, &value);
684 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
685 "Unable to get Gurobi solution (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
686
688}
689
690template<typename ValueType, bool RawMode>
691void GurobiLpSolver<ValueType, RawMode>::setMaximalMILPGap(ValueType const& gap, bool relative) {
692 int error = -1;
693 if (relative) {
694 error = GRBsetdblparam(GRBgetenv(model), GRB_DBL_PAR_MIPGAP, storm::utility::convertNumber<double>(gap));
695 } else {
696 error = GRBsetdblparam(GRBgetenv(model), GRB_DBL_PAR_MIPGAPABS, storm::utility::convertNumber<double>(gap));
697 }
698 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
699 "Unable to set Gurobi MILP GAP (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
700}
701
702template<typename ValueType, bool RawMode>
704 double relativeGap;
705 int error = GRBgetdblattr(model, GRB_DBL_ATTR_MIPGAP, &relativeGap);
706 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
707 "Unable to get Gurobi MILP GAP (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
708 auto result = storm::utility::convertNumber<ValueType>(relativeGap);
709 if (relative) {
710 return result;
711 } else {
712 return storm::utility::abs<ValueType>(result * getObjectiveValue());
713 }
714}
715
716template<typename ValueType, bool RawMode>
718 int error = GRBsetdblparam(GRBgetenv(model), GRB_DBL_PAR_TIMELIMIT, seconds);
719 timeLimit.emplace(seconds);
720 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
721 "Unable to set Gurobi time limit (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
722}
723
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();
728}
729
730template<typename ValueType, bool RawMode>
732 return timeLimit.has_value();
733}
734
735template<typename ValueType, bool RawMode>
737 if (!this->currentModelHasBeenOptimized) {
738 return false;
739 }
740 int status = 0;
741
742 int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &status);
743 STORM_LOG_THROW(error == 0, storm::exceptions::InvalidStateException,
744 "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(**environment) << ", error code " << error << ").");
745
746 return status == GRB_TIME_LIMIT;
747}
748
749#else
750template<typename ValueType, bool RawMode>
751GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const&, std::string const&, OptimizationDirection const&) {
752 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
755}
756
757template<typename ValueType, bool RawMode>
758GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const&, std::string const&) {
759 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
762}
763
764template<typename ValueType, bool RawMode>
765GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const&, OptimizationDirection const&) {
766 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
769}
770
771template<typename ValueType, bool RawMode>
772GurobiLpSolver<ValueType, RawMode>::GurobiLpSolver(std::shared_ptr<GurobiEnvironment> const&) {
773 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
776}
777
778template<typename ValueType, bool RawMode>
780
781template<typename ValueType, bool RawMode>
783 std::optional<ValueType> const&,
784 std::optional<ValueType> const&, ValueType) {
785 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
788}
789
790template<typename ValueType, bool RawMode>
792 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
795}
796
797template<typename ValueType, bool RawMode>
799 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
802}
803
804template<typename ValueType, bool RawMode>
806 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
809}
810
811template<typename ValueType, bool RawMode>
813 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
816}
817
818template<typename ValueType, bool RawMode>
820 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
823}
824
825template<typename ValueType, bool RawMode>
827 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
830}
831
832template<typename ValueType, bool RawMode>
834 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
837}
838
839template<typename ValueType, bool RawMode>
841 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
844}
845
846template<typename ValueType, bool RawMode>
848 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
851}
852
853template<typename ValueType, bool RawMode>
855 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
858}
859
860template<typename ValueType, bool RawMode>
862 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
865}
866
867template<typename ValueType, bool RawMode>
869 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
872}
873
874template<typename ValueType, bool RawMode>
876 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
879}
880
881template<typename ValueType, bool RawMode>
883 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
886}
887
888template<typename ValueType, bool RawMode>
890 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
893}
894
895template<typename ValueType, bool RawMode>
897 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
900}
901
902template<typename ValueType, bool RawMode>
903ValueType GurobiLpSolver<ValueType, RawMode>::getContinuousValue(Variable const&, uint64_t const&) const {
904 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
907}
908
909template<typename ValueType, bool RawMode>
910int_fast64_t GurobiLpSolver<ValueType, RawMode>::getIntegerValue(Variable const&, uint64_t const&) const {
911 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
914}
915
916template<typename ValueType, bool RawMode>
918 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
921}
922
923template<typename ValueType, bool RawMode>
925 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
928}
929
930template<typename ValueType, bool RawMode>
932 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
935}
936
937template<typename ValueType, bool RawMode>
939 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
942}
943
944template<typename ValueType, bool RawMode>
946 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
949}
950
951template<typename ValueType, bool RawMode>
953 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
956}
957
958template<typename ValueType, bool RawMode>
960 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
963}
964
965template<typename ValueType, bool RawMode>
967 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
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.");
970}
971
972#endif
973
974std::string toString(GurobiSolverMethod const& method) {
975 switch (method) {
977 return "auto";
979 return "primal-simplex";
981 return "dual-simplex";
983 return "barrier";
985 return "concurrent";
987 return "deterministic-concurrent";
989 return "deterministic-concurrent-simplex";
990 }
991 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unknown solver method.");
992}
993
994std::optional<GurobiSolverMethod> gurobiSolverMethodFromString(std::string const& method) {
995 for (auto const& mt : getGurobiSolverMethods()) {
996 if (toString(mt) == method) {
997 return mt;
998 }
999 }
1000 return {};
1001}
1002
1007
1008template class GurobiLpSolver<double, true>;
1009template class GurobiLpSolver<double, false>;
1010template class GurobiLpSolver<storm::RationalNumber, true>;
1011template class GurobiLpSolver<storm::RationalNumber, false>;
1012} // namespace solver
1013} // namespace storm
storm::solver::GurobiSolverMethod const & getMethod() const
void initialize(storm::GurobiSolverEnvironment const &gurobiSettings, bool debug)
Sets some properties of the Gurobi environment according to parameters given by the options.
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
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.
Definition LpSolver.h:50
#define STORM_LOG_TRACE(message)
Definition logging.h:15
#define STORM_LOG_ERROR(message)
Definition logging.h:29
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:50
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:28
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].
Definition vector.h:129
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