Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
HighsLpSolver.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <limits>
5
17
18namespace storm {
19namespace solver {
20
21#ifdef STORM_HAVE_HIGHS
22
23namespace {
24
25constexpr double highInfinity = std::numeric_limits<double>::infinity();
26
27struct HighsConstraintData {
28 std::vector<HighsInt> variableIndices;
29 std::vector<double> coefficients;
30 double rhs;
32};
33
34template<typename ValueType, bool RawMode>
35HighsConstraintData createConstraintData(typename HighsLpSolver<ValueType, RawMode>::Constraint const& constraint,
36 std::map<storm::expressions::Variable, uint64_t> const& variableToIndexMap) {
37 HighsConstraintData result;
38 if constexpr (RawMode) {
39 result.rhs = storm::utility::convertNumber<double>(constraint.rhs);
40 result.relationType = constraint.relationType;
41 result.variableIndices.reserve(constraint.lhsVariableIndices.size());
42 result.coefficients.reserve(constraint.lhsCoefficients.size());
43 for (auto const& variable : constraint.lhsVariableIndices) {
44 result.variableIndices.push_back(static_cast<HighsInt>(variable));
45 }
46 for (auto const& coefficient : constraint.lhsCoefficients) {
47 result.coefficients.push_back(storm::utility::convertNumber<double>(coefficient));
48 }
49 } else {
50 STORM_LOG_THROW(constraint.isRelationalExpression(), storm::exceptions::InvalidArgumentException, "Illegal constraint is not a relational expression.");
51 storm::expressions::LinearCoefficientVisitor::VariableCoefficients leftCoefficients =
52 storm::expressions::LinearCoefficientVisitor().getLinearCoefficients(constraint.getOperand(0));
53 storm::expressions::LinearCoefficientVisitor::VariableCoefficients rightCoefficients =
54 storm::expressions::LinearCoefficientVisitor().getLinearCoefficients(constraint.getOperand(1));
55 leftCoefficients.separateVariablesFromConstantPart(rightCoefficients);
56 result.rhs = storm::utility::convertNumber<double>(rightCoefficients.getConstantPart());
57 result.relationType = constraint.getBaseExpression().asBinaryRelationExpression().getRelationType();
58 result.variableIndices.reserve(leftCoefficients.size());
59 result.coefficients.reserve(leftCoefficients.size());
60 for (auto const& variableCoefficientPair : leftCoefficients) {
61 auto variableIndexPair = variableToIndexMap.find(variableCoefficientPair.first);
62 result.variableIndices.push_back(static_cast<HighsInt>(variableIndexPair->second));
63 result.coefficients.push_back(storm::utility::convertNumber<double>(variableCoefficientPair.second));
64 }
65 }
66 return result;
67}
68
69} // namespace
70
71template<typename ValueType, bool RawMode>
73 : LpSolver<ValueType, RawMode>(optDir), nextVariableIndex(0) {
74 // By default, HiGHS prints its log to the command line. We disable this as storm provides its own logging.
75 highs.setOptionValue("output_flag", false);
76}
77
78template<typename ValueType, bool RawMode>
79HighsLpSolver<ValueType, RawMode>::HighsLpSolver(std::string const& name) : HighsLpSolver(name, OptimizationDirection::Minimize) {}
80
81template<typename ValueType, bool RawMode>
82HighsLpSolver<ValueType, RawMode>::HighsLpSolver(OptimizationDirection const& optDir) : HighsLpSolver("", optDir) {}
83
84template<typename ValueType, bool RawMode>
85HighsLpSolver<ValueType, RawMode>::HighsLpSolver() : HighsLpSolver("", OptimizationDirection::Minimize) {}
86
87template<typename ValueType, bool RawMode>
88HighsLpSolver<ValueType, RawMode>::~HighsLpSolver() {}
89
90template<typename ValueType, bool RawMode>
91double HighsLpSolver<ValueType, RawMode>::toHighsBound(double value) const {
92 if (!std::isfinite(value)) {
93 return value > 0 ? highs.getInfinity() : -highs.getInfinity();
94 }
95 return value;
96}
97
98template<typename ValueType, bool RawMode>
99typename HighsLpSolver<ValueType, RawMode>::Variable HighsLpSolver<ValueType, RawMode>::addVariable(std::string const& name, VariableType const& type,
100 std::optional<ValueType> const& lowerBound,
101 std::optional<ValueType> const& upperBound,
102 ValueType objectiveFunctionCoefficient) {
103 Variable resultVar;
104 if constexpr (RawMode) {
105 resultVar = nextVariableIndex;
106 } else {
107 resultVar = this->declareOrGetExpressionVariable(name, type);
108 STORM_LOG_ASSERT(variableToIndexMap.count(resultVar) == 0, "Variable " << resultVar.getName() << " exists already in the model.");
109 this->variableToIndexMap.emplace(resultVar, nextVariableIndex);
110 }
111
112 double lower = lowerBound.has_value() ? storm::utility::convertNumber<double>(*lowerBound) : -highInfinity;
113 double upper = upperBound.has_value() ? storm::utility::convertNumber<double>(*upperBound) : highInfinity;
114 if (type == VariableType::Binary) {
115 lower = 0.0;
116 upper = 1.0;
117 }
118
119 HighsStatus addColStatus =
120 highs.addCol(storm::utility::convertNumber<double>(objectiveFunctionCoefficient), toHighsBound(lower), toHighsBound(upper), 0, nullptr, nullptr);
121 STORM_LOG_THROW(addColStatus != HighsStatus::kError, storm::exceptions::InvalidStateException, "Unable to add variable to HiGHS model.");
122 HighsInt column = static_cast<HighsInt>(nextVariableIndex);
123
124 if (type != VariableType::Continuous) {
125 HighsStatus integralityStatus = highs.changeColIntegrality(column, HighsVarType::kInteger);
126 STORM_LOG_THROW(integralityStatus != HighsStatus::kError, storm::exceptions::InvalidStateException, "Unable to set integrality of HiGHS variable.");
127 }
128 if (!name.empty()) {
129 highs.passColName(column, name);
130 }
131
132 variableBounds.emplace_back(lower, upper);
133 ++nextVariableIndex;
134 return resultVar;
135}
136
137template<typename ValueType, bool RawMode>
138void HighsLpSolver<ValueType, RawMode>::update() const {
139 // HiGHS accepts incremental changes to the model at any point in time, so there is nothing to do here.
140}
141
142template<typename ValueType, bool RawMode>
143void HighsLpSolver<ValueType, RawMode>::addConstraint(std::string const&, Constraint const& constraint) {
144 if constexpr (!RawMode) {
145 STORM_LOG_ASSERT(constraint.getManager() == this->getManager(), "Constraint was not built over the proper variables.");
146 }
147
148 auto constraintData = createConstraintData<ValueType, RawMode>(constraint, this->variableToIndexMap);
149
150 double lower, upper;
151 switch (constraintData.relationType) {
154 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "HiGHS only supports nonstrict inequalities.");
155 break;
157 lower = -highInfinity;
158 upper = constraintData.rhs;
159 break;
161 lower = constraintData.rhs;
162 upper = highInfinity;
163 break;
165 lower = constraintData.rhs;
166 upper = constraintData.rhs;
167 break;
168 default:
169 STORM_LOG_ASSERT(false, "Illegal operator in LP solver constraint.");
170 }
171 highs.addRow(toHighsBound(lower), toHighsBound(upper), constraintData.variableIndices.size(), constraintData.variableIndices.data(),
172 constraintData.coefficients.data());
173}
174
175template<typename ValueType, bool RawMode>
176void HighsLpSolver<ValueType, RawMode>::addIndicatorConstraint(std::string const&, Variable indicatorVariable, bool indicatorValue,
177 Constraint const& constraint) {
178 if constexpr (RawMode) {
179 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Indicator constraints not implemented in RawMode.");
180 } else {
181 STORM_LOG_ASSERT(this->variableToIndexMap.count(indicatorVariable) > 0, "Indicator Variable " << indicatorVariable.getName() << " unknown to solver.");
182 STORM_LOG_ASSERT(indicatorVariable.hasIntegerType(), "Indicator Variable " << indicatorVariable.getName() << " has unexpected type.");
183 STORM_LOG_ASSERT(constraint.getManager() == this->getManager(), "Constraint was not built over the proper variables.");
184
185 auto constraintData = createConstraintData<ValueType, RawMode>(constraint, this->variableToIndexMap);
186 if (constraintData.relationType == storm::expressions::RelationType::Less || constraintData.relationType == storm::expressions::RelationType::Greater) {
187 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "HiGHS only supports nonstrict inequalities.");
188 }
189
190 // HiGHS does not support indicator constraints natively. Instead, we apply a big-M reformulation that reuses the binary indicator variable.
191 // To this end, we compute bounds on the activity of the constraint's linear expression over the box given by the variable bounds.
192 double minActivity = 0.0;
193 double maxActivity = 0.0;
194 for (std::size_t i = 0; i < constraintData.variableIndices.size(); ++i) {
195 double coefficient = constraintData.coefficients[i];
196 auto const& bounds = variableBounds[constraintData.variableIndices[i]];
197 double lowerBound = bounds.first;
198 double upperBound = bounds.second;
199 if (coefficient > 0) {
200 maxActivity += coefficient * (std::isfinite(upperBound) ? upperBound : highInfinity);
201 minActivity += coefficient * (std::isfinite(lowerBound) ? lowerBound : -highInfinity);
202 } else if (coefficient < 0) {
203 maxActivity += coefficient * (std::isfinite(lowerBound) ? lowerBound : -highInfinity);
204 minActivity += coefficient * (std::isfinite(upperBound) ? upperBound : highInfinity);
205 }
206 }
207
208 HighsInt indicatorIndex = static_cast<HighsInt>(this->variableToIndexMap.at(indicatorVariable));
209
210 auto addIndicatorRow = [this, &constraintData, indicatorIndex](double mCoefficient, double newRhs, bool isLessEqual) {
211 std::vector<HighsInt> variableIndices = constraintData.variableIndices;
212 std::vector<double> coefficients = constraintData.coefficients;
213 variableIndices.push_back(indicatorIndex);
214 coefficients.push_back(mCoefficient);
215 double lower = -highInfinity;
216 double upper = highInfinity;
217 if (isLessEqual) {
218 upper = newRhs;
219 } else {
220 lower = newRhs;
221 }
222 highs.addRow(toHighsBound(lower), toHighsBound(upper), variableIndices.size(), variableIndices.data(), coefficients.data());
223 };
224
225 auto addSingleIndicatorConstraint = [&](bool isLessEqual, bool indicatorValue) {
226 double m;
227 if (isLessEqual) {
228 m = maxActivity - constraintData.rhs;
229 } else {
230 m = constraintData.rhs - minActivity;
231 }
232 STORM_LOG_THROW(std::isfinite(m), storm::exceptions::NotSupportedException,
233 "Indicator constraints over unbounded variables are not supported by the HiGHS solver.");
234 double mCoefficient = (indicatorValue == isLessEqual) ? m : -m;
235 double newRhs = constraintData.rhs;
236 if (indicatorValue) {
237 newRhs += isLessEqual ? m : -m;
238 }
239 addIndicatorRow(mCoefficient, newRhs, isLessEqual);
240 };
241
242 switch (constraintData.relationType) {
244 addSingleIndicatorConstraint(true, indicatorValue);
245 break;
247 addSingleIndicatorConstraint(false, indicatorValue);
248 break;
250 addSingleIndicatorConstraint(true, indicatorValue);
251 addSingleIndicatorConstraint(false, indicatorValue);
252 break;
253 default:
254 STORM_LOG_ASSERT(false, "Illegal operator in LP solver constraint.");
255 }
256 }
257}
258
259template<typename ValueType, bool RawMode>
260void HighsLpSolver<ValueType, RawMode>::optimize() const {
261 // First incorporate all recent changes.
262 this->update();
263
264 // Set the model sense.
265 highs.changeObjectiveSense(this->getOptimizationDirection() == OptimizationDirection::Minimize ? ObjSense::kMinimize : ObjSense::kMaximize);
266
267 // Then we actually optimize the model.
268 HighsStatus status = highs.run();
269 STORM_LOG_THROW(status != HighsStatus::kError, storm::exceptions::InvalidStateException, "Unable to optimize the model with HiGHS.");
270
271 this->currentModelHasBeenOptimized = true;
272 modelStatus = highs.getModelStatus();
273}
274
275template<typename ValueType, bool RawMode>
276bool HighsLpSolver<ValueType, RawMode>::isInfeasible() const {
277 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidStateException,
278 "Illegal call to HighsLpSolver<ValueType, RawMode>::isInfeasible: model has not been optimized.");
279 return modelStatus == HighsModelStatus::kInfeasible;
280}
281
282template<typename ValueType, bool RawMode>
283bool HighsLpSolver<ValueType, RawMode>::isUnbounded() const {
284 STORM_LOG_THROW(this->currentModelHasBeenOptimized, storm::exceptions::InvalidStateException,
285 "Illegal call to HighsLpSolver<ValueType, RawMode>::isUnbounded: model has not been optimized.");
286 return modelStatus == HighsModelStatus::kUnbounded || modelStatus == HighsModelStatus::kUnboundedOrInfeasible;
287}
288
289template<typename ValueType, bool RawMode>
290bool HighsLpSolver<ValueType, RawMode>::isOptimal() const {
291 if (!this->currentModelHasBeenOptimized) {
292 return false;
293 }
294 return modelStatus == HighsModelStatus::kOptimal;
295}
296
297template<typename ValueType, bool RawMode>
298ValueType HighsLpSolver<ValueType, RawMode>::getContinuousValue(Variable const& variable) const {
299 STORM_LOG_THROW(this->isOptimal(), storm::exceptions::InvalidAccessException,
300 "Unable to get HiGHS solution from a model that has not been solved optimally.");
301
302 uint64_t variableIndex;
303 if constexpr (RawMode) {
304 variableIndex = variable;
305 } else {
306 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
307 "Accessing value of unknown variable '" << variable.getName() << "'.");
308 variableIndex = variableToIndexMap.at(variable);
309 }
310 STORM_LOG_ASSERT(variableIndex < nextVariableIndex, "Variable Index exceeds highest value.");
311
312 return storm::utility::convertNumber<ValueType>(highs.getSolution().col_value[variableIndex]);
313}
314
315template<typename ValueType, bool RawMode>
316int_fast64_t HighsLpSolver<ValueType, RawMode>::getIntegerValue(Variable const& variable) const {
317 STORM_LOG_THROW(this->isOptimal(), storm::exceptions::InvalidAccessException,
318 "Unable to get HiGHS solution from a model that has not been solved optimally.");
319
320 uint64_t variableIndex;
321 if constexpr (RawMode) {
322 variableIndex = variable;
323 } else {
324 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
325 "Accessing value of unknown variable '" << variable.getName() << "'.");
326 variableIndex = variableToIndexMap.at(variable);
327 }
328 STORM_LOG_ASSERT(variableIndex < nextVariableIndex, "Variable Index exceeds highest value.");
329
330 return std::llround(highs.getSolution().col_value[variableIndex]);
331}
332
333template<typename ValueType, bool RawMode>
334bool HighsLpSolver<ValueType, RawMode>::getBinaryValue(Variable const& variable) const {
335 STORM_LOG_THROW(this->isOptimal(), storm::exceptions::InvalidAccessException,
336 "Unable to get HiGHS solution from a model that has not been solved optimally.");
337
338 uint64_t variableIndex;
339 if constexpr (RawMode) {
340 variableIndex = variable;
341 } else {
342 STORM_LOG_THROW(variableToIndexMap.count(variable) != 0, storm::exceptions::InvalidAccessException,
343 "Accessing value of unknown variable '" << variable.getName() << "'.");
344 variableIndex = variableToIndexMap.at(variable);
345 }
346 STORM_LOG_ASSERT(variableIndex < nextVariableIndex, "Variable Index exceeds highest value.");
347
348 return highs.getSolution().col_value[variableIndex] > 0.5;
349}
350
351template<typename ValueType, bool RawMode>
352ValueType HighsLpSolver<ValueType, RawMode>::getObjectiveValue() const {
353 STORM_LOG_THROW(this->isOptimal(), storm::exceptions::InvalidAccessException,
354 "Unable to get HiGHS solution from a model that has not been solved optimally.");
355 return storm::utility::convertNumber<ValueType>(highs.getObjectiveValue());
356}
357
358template<typename ValueType, bool RawMode>
359void HighsLpSolver<ValueType, RawMode>::writeModelToFile(std::string const& filename) const {
360 HighsStatus status = highs.writeModel(filename);
361 STORM_LOG_THROW(status != HighsStatus::kError, storm::exceptions::InvalidStateException, "Unable to write HiGHS model to file '" << filename << "'.");
362}
363
364template<typename ValueType, bool RawMode>
365void HighsLpSolver<ValueType, RawMode>::push() {
366 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Push/Pop not supported for HiGHS.");
367}
368
369template<typename ValueType, bool RawMode>
370void HighsLpSolver<ValueType, RawMode>::pop() {
371 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Push/Pop not supported for HiGHS.");
372}
373
374template<typename ValueType, bool RawMode>
375void HighsLpSolver<ValueType, RawMode>::setMaximalMILPGap(ValueType const& gap, bool relative) {
376 double gapAsDouble = storm::utility::convertNumber<double>(gap);
377 HighsStatus status = relative ? highs.setOptionValue("mip_rel_gap", gapAsDouble) : highs.setOptionValue("mip_abs_gap", gapAsDouble);
378 STORM_LOG_THROW(status != HighsStatus::kError, storm::exceptions::InvalidStateException, "Unable to set HiGHS MILP gap.");
379}
380
381template<typename ValueType, bool RawMode>
382ValueType HighsLpSolver<ValueType, RawMode>::getMILPGap(bool relative) const {
383 auto const& info = highs.getInfo();
384 // HiGHS reports the relative MILP gap as a percentage.
385 double relativeGap = info.mip_gap / 100.0;
386 auto result = storm::utility::convertNumber<ValueType>(relativeGap);
387 if (relative) {
388 return result;
389 } else {
390 return storm::utility::abs<ValueType>(result * getObjectiveValue());
391 }
392}
393
394#else
395
396template<typename ValueType, bool RawMode>
398 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
399 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
400 "version of storm with HiGHS support.");
401}
402
403template<typename ValueType, bool RawMode>
405 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
406 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
407 "version of storm with HiGHS support.");
408}
409
410template<typename ValueType, bool RawMode>
412 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
413 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
414 "version of storm with HiGHS support.");
415}
416
417template<typename ValueType, bool RawMode>
419 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
420 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
421 "version of storm with HiGHS support.");
422}
423
424template<typename ValueType, bool RawMode>
426
427template<typename ValueType, bool RawMode>
429 std::optional<ValueType> const&,
430 std::optional<ValueType> const&, ValueType) {
431 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
432 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
433 "version of storm with HiGHS support.");
434}
435
436template<typename ValueType, bool RawMode>
438 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
439 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
440 "version of storm with HiGHS support.");
441}
442
443template<typename ValueType, bool RawMode>
445 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
446 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
447 "version of storm with HiGHS support.");
448}
449
450template<typename ValueType, bool RawMode>
452 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
453 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
454 "version of storm with HiGHS support.");
455}
456
457template<typename ValueType, bool RawMode>
459 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
460 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
461 "version of storm with HiGHS support.");
462}
463
464template<typename ValueType, bool RawMode>
466 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
467 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
468 "version of storm with HiGHS support.");
469}
470
471template<typename ValueType, bool RawMode>
473 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
474 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
475 "version of storm with HiGHS support.");
476}
477
478template<typename ValueType, bool RawMode>
480 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
481 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
482 "version of storm with HiGHS support.");
483}
484
485template<typename ValueType, bool RawMode>
487 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
488 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
489 "version of storm with HiGHS support.");
490}
491
492template<typename ValueType, bool RawMode>
494 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
495 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
496 "version of storm with HiGHS support.");
497}
498
499template<typename ValueType, bool RawMode>
501 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
502 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
503 "version of storm with HiGHS support.");
504}
505
506template<typename ValueType, bool RawMode>
508 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
509 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
510 "version of storm with HiGHS support.");
511}
512
513template<typename ValueType, bool RawMode>
515 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
516 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
517 "version of storm with HiGHS support.");
518}
519
520template<typename ValueType, bool RawMode>
522 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
523 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
524 "version of storm with HiGHS support.");
525}
526
527template<typename ValueType, bool RawMode>
529 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
530 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
531 "version of storm with HiGHS support.");
532}
533
534template<typename ValueType, bool RawMode>
536 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
537 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
538 "version of storm with HiGHS support.");
539}
540
541template<typename ValueType, bool RawMode>
543 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
544 "This version of storm was compiled without support for HiGHS. Yet, a method was called that requires this support. Please choose a "
545 "version of storm with HiGHS support.");
546}
547
548#endif
549
550template class HighsLpSolver<double, true>;
551template class HighsLpSolver<double, false>;
552
553} // namespace solver
554} // namespace storm
A class that implements the LpSolver interface using HiGHS.
virtual void optimize() const override
Optimizes the LP problem previously constructed.
virtual void update() const override
Updates the model to make the variables that have been declared since the last call to update usable.
HighsLpSolver(std::string const &name, OptimizationDirection const &optDir)
Constructs a solver with the given name and model sense.
virtual void addConstraint(std::string const &name, Constraint const &constraint) override
Adds a the given constraint to the LP problem.
virtual void setMaximalMILPGap(ValueType const &gap, bool relative) override
Specifies the maximum difference between lower- and upper objective bounds that triggers termination.
typename LpSolver< ValueType, RawMode >::Constraint Constraint
virtual void pop() override
Pops a backtracking point from the solver's stack.
virtual int_fast64_t getIntegerValue(Variable const &variable) const override
Retrieves the value of the integer variable with the given name.
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 >::Variable Variable
virtual ValueType getMILPGap(bool relative) const override
Returns the obtained gap after a call to optimize().
virtual void writeModelToFile(std::string const &filename) const override
Writes the current LP problem to the given file.
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,...
HighsLpSolver()
Constructs a solver without a name.
virtual void push() override
Pushes a backtracking point on the solver's stack.
typename LpSolver< ValueType, RawMode >::VariableType VariableType
virtual bool isOptimal() const override
Retrieves whether the model was found to be optimal, i.e.
virtual bool getBinaryValue(Variable const &variable) const override
Retrieves the value of the binary variable with the given name.
virtual bool isInfeasible() const override
Retrieves whether the model was found to be infeasible.
virtual ValueType getContinuousValue(Variable const &variable) const override
Retrieves the value of the continuous variable with the given name.
virtual ValueType getObjectiveValue() const override
Retrieves the value of the objective function.
virtual bool isUnbounded() const override
Retrieves whether the model was found to be infeasible.
An interface that captures the functionality of an LP solver.
Definition LpSolver.h:50
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:28
SFTBDDChecker::ValueType ValueType
RelationType
An enum type specifying the different relations applicable.
ValueType abs(ValueType const &number)
TargetType convertNumber(SourceType const &number)
void separateVariablesFromConstantPart(VariableCoefficients &rhs)
Brings all variables of the right-hand side coefficients to the left-hand side by negating them and m...