1#include "storm-config.h"
15class DefaultEnvironment {
18 static const bool isExact =
false;
19 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::FROMSETTINGS;
20 static const bool IntegerSupport =
true;
21 static const bool IncrementalSupport =
true;
22 static const bool strictRelationSupport =
true;
25#ifdef STORM_HAVE_LP_SOLVER
33class GlpkEnvironment {
36 static const bool isExact =
false;
37 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Glpk;
38 static const bool IntegerSupport =
true;
39 static const bool IncrementalSupport =
true;
40 static const bool strictRelationSupport =
true;
47#ifdef STORM_HAVE_GUROBI
48class GurobiEnvironment {
51 static const bool isExact =
false;
52 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Gurobi;
53 static const bool IntegerSupport =
true;
54 static const bool IncrementalSupport =
true;
55 static const bool strictRelationSupport =
true;
66 static const bool isExact =
true;
67 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Z3;
68 static const bool IntegerSupport =
true;
69 static const bool IncrementalSupport =
true;
70 static const bool strictRelationSupport =
true;
77#ifdef STORM_HAVE_SOPLEX
78class SoplexEnvironment {
81 static const bool isExact =
false;
82 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Soplex;
83 static const bool IntegerSupport =
false;
84 static const bool IncrementalSupport =
false;
85 static const bool strictRelationSupport =
false;
92class SoplexExactEnvironment {
95 static const bool isExact =
true;
96 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Soplex;
97 static const bool IntegerSupport =
false;
98 static const bool IncrementalSupport =
false;
99 static const bool strictRelationSupport =
false;
107template<
typename TestType>
108class LpSolverTest :
public ::testing::Test {
110 typedef typename TestType::ValueType
ValueType;
112 void SetUp()
override {
118 storm::solver::LpSolverTypeSelection solverSelection()
const {
119 return TestType::solverSelection;
122 std::unique_ptr<storm::utility::solver::LpSolverFactory<ValueType>> factory()
const {
123 return storm::utility::solver::getLpSolverFactory<ValueType>(solverSelection());
127 return storm::utility::convertNumber<ValueType>(input);
134 bool supportsInteger()
const {
135 return TestType::IntegerSupport;
138 bool supportsIncremental()
const {
139 return TestType::IncrementalSupport;
142 bool supportsStrictRelation()
const {
143 return TestType::strictRelationSupport;
146 bool skipped()
const {
147 return TestType::skip();
151typedef ::testing::Types<DefaultEnvironment
152#ifdef STORM_HAVE_GLPK
156#ifdef STORM_HAVE_GUROBI
160#ifdef STORM_HAVE_Z3_OPTIMIZE
164#ifdef STORM_HAVE_SOPLEX
166 SoplexEnvironment, SoplexExactEnvironment
174 typedef typename TestFixture::ValueType
ValueType;
175 auto solver = this->factory()->create(
"");
176 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
180 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
181 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
182 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
183 ASSERT_NO_THROW(solver->update());
185 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
186 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
187 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
188 ASSERT_NO_THROW(solver->update());
190 ASSERT_NO_THROW(solver->optimize());
191 ASSERT_TRUE(solver->isOptimal());
192 ASSERT_FALSE(solver->isUnbounded());
193 ASSERT_FALSE(solver->isInfeasible());
194 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(x), this->precision());
195 EXPECT_NEAR(this->
parseNumber(
"13/2"), solver->getContinuousValue(y), this->precision());
196 EXPECT_NEAR(this->
parseNumber(
"11/4"), solver->getContinuousValue(z), this->precision());
197 EXPECT_NEAR(this->
parseNumber(
"59/4"), solver->getObjectiveValue(), this->precision());
201 typedef typename TestFixture::ValueType
ValueType;
202 auto solver = this->factory()->createRaw(
"");
203 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
204 ASSERT_EQ(0u, solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
205 ASSERT_EQ(1u, solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
206 ASSERT_EQ(2u, solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
207 ASSERT_NO_THROW(solver->update());
214 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
220 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
225 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
226 ASSERT_NO_THROW(solver->update());
228 ASSERT_NO_THROW(solver->optimize());
229 ASSERT_TRUE(solver->isOptimal());
230 ASSERT_FALSE(solver->isUnbounded());
231 ASSERT_FALSE(solver->isInfeasible());
232 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(0), this->precision());
233 EXPECT_NEAR(this->
parseNumber(
"13/2"), solver->getContinuousValue(1), this->precision());
234 EXPECT_NEAR(this->
parseNumber(
"11/4"), solver->getContinuousValue(2), this->precision());
235 EXPECT_NEAR(this->
parseNumber(
"59/4"), solver->getObjectiveValue(), this->precision());
239 typedef typename TestFixture::ValueType
ValueType;
240 auto solver = this->factory()->create(
"");
241 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
245 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
246 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
247 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
248 ASSERT_NO_THROW(solver->update());
250 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
251 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
252 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
253 ASSERT_NO_THROW(solver->update());
255 ASSERT_NO_THROW(solver->optimize());
256 ASSERT_TRUE(solver->isOptimal());
257 ASSERT_FALSE(solver->isUnbounded());
258 ASSERT_FALSE(solver->isInfeasible());
260 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(x), this->precision());
261 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(y), this->precision());
262 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(z), this->precision());
263 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
267 typedef typename TestFixture::ValueType
ValueType;
268 auto solver = this->factory()->createRaw(
"");
269 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
271 ASSERT_EQ(0u, solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
272 ASSERT_EQ(1u, solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
273 ASSERT_EQ(2u, solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
274 ASSERT_NO_THROW(solver->update());
281 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
287 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
292 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
293 ASSERT_NO_THROW(solver->update());
295 ASSERT_NO_THROW(solver->optimize());
296 ASSERT_TRUE(solver->isOptimal());
297 ASSERT_FALSE(solver->isUnbounded());
298 ASSERT_FALSE(solver->isInfeasible());
300 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(0), this->precision());
301 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(1), this->precision());
302 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(2), this->precision());
303 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
307 if (!this->supportsInteger()) {
310 typedef typename TestFixture::ValueType
ValueType;
311 auto solver = this->factory()->create(
"");
312 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
316 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
317 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
318 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
319 ASSERT_NO_THROW(solver->update());
321 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
322 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
323 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
324 ASSERT_NO_THROW(solver->update());
325 ASSERT_NO_THROW(solver->optimize());
326 ASSERT_TRUE(solver->isOptimal());
327 ASSERT_FALSE(solver->isUnbounded());
328 ASSERT_FALSE(solver->isInfeasible());
330 EXPECT_TRUE(solver->getBinaryValue(x));
331 EXPECT_EQ(6, solver->getIntegerValue(y));
332 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(z), this->precision());
333 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
337 if (!this->supportsInteger()) {
340 typedef typename TestFixture::ValueType
ValueType;
341 auto solver = this->factory()->createRaw(
"");
342 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
346 ASSERT_EQ(0u, solver->addBinaryVariable(
"x", -1));
347 ASSERT_EQ(1u, solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
348 ASSERT_EQ(2u, solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
349 ASSERT_NO_THROW(solver->update());
356 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
362 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
367 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
368 ASSERT_NO_THROW(solver->update());
370 ASSERT_NO_THROW(solver->optimize());
371 ASSERT_TRUE(solver->isOptimal());
372 ASSERT_FALSE(solver->isUnbounded());
373 ASSERT_FALSE(solver->isInfeasible());
374 EXPECT_TRUE(solver->getBinaryValue(0));
375 EXPECT_EQ(6, solver->getIntegerValue(1));
376 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(2), this->precision());
377 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
381 if (!this->supportsInteger()) {
384 typedef typename TestFixture::ValueType
ValueType;
385 auto solver = this->factory()->create(
"");
386 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
390 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
391 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
392 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 0, 5, -1));
393 ASSERT_NO_THROW(solver->update());
395 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
396 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
397 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
398 ASSERT_NO_THROW(solver->update());
400#ifdef STORM_HAVE_Z3_OPTIMIZE
401 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && storm::test::z3AtLeastVersion(4, 8, 8)) {
403 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
407 ASSERT_NO_THROW(solver->optimize());
408 ASSERT_TRUE(solver->isOptimal());
409 ASSERT_FALSE(solver->isUnbounded());
410 ASSERT_FALSE(solver->isInfeasible());
412 EXPECT_TRUE(solver->getBinaryValue(x));
413 EXPECT_EQ(0, solver->getIntegerValue(y));
414 EXPECT_NEAR(this->
parseNumber(
"5"), solver->getContinuousValue(z), this->precision());
415 EXPECT_NEAR(this->
parseNumber(
"-6"), solver->getObjectiveValue(), this->precision());
419 typedef typename TestFixture::ValueType
ValueType;
420 auto solver = this->factory()->create(
"");
421 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
425 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
426 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
427 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
428 ASSERT_NO_THROW(solver->update());
430 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
431 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
432 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
433 if (this->supportsStrictRelation()) {
434 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
436 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
438 ASSERT_NO_THROW(solver->update());
440 ASSERT_NO_THROW(solver->optimize());
441 ASSERT_FALSE(solver->isOptimal());
442 ASSERT_FALSE(solver->isUnbounded());
443 ASSERT_TRUE(solver->isInfeasible());
451 if (!this->supportsInteger()) {
454 typedef typename TestFixture::ValueType
ValueType;
455 auto solver = this->factory()->create(
"");
456 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
460 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
461 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
462 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
463 ASSERT_NO_THROW(solver->update());
465 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
466 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
467 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
468 if (this->supportsStrictRelation()) {
469 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
471 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
473 ASSERT_NO_THROW(solver->update());
475 ASSERT_NO_THROW(solver->optimize());
476 ASSERT_FALSE(solver->isOptimal());
477 ASSERT_FALSE(solver->isUnbounded());
478 ASSERT_TRUE(solver->isInfeasible());
486 typedef typename TestFixture::ValueType
ValueType;
487 auto solver = this->factory()->create(
"");
488 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
492 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
493 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
494 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
495 ASSERT_NO_THROW(solver->update());
497 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
498 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
499 ASSERT_NO_THROW(solver->update());
501 ASSERT_NO_THROW(solver->optimize());
502 ASSERT_FALSE(solver->isOptimal());
503 ASSERT_TRUE(solver->isUnbounded());
504 ASSERT_FALSE(solver->isInfeasible());
512 if (!this->supportsInteger()) {
515 typedef typename TestFixture::ValueType
ValueType;
516 auto solver = this->factory()->create(
"");
517 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
521 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
522 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
523 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
524 ASSERT_NO_THROW(solver->update());
526 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
527 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
528 ASSERT_NO_THROW(solver->update());
530 ASSERT_NO_THROW(solver->optimize());
531 ASSERT_FALSE(solver->isOptimal());
532 ASSERT_TRUE(solver->isUnbounded());
533 ASSERT_FALSE(solver->isInfeasible());
541 if (!this->supportsIncremental()) {
544 typedef typename TestFixture::ValueType
ValueType;
545 auto solver = this->factory()->create(
"");
546 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
548 ASSERT_NO_THROW(x = solver->addUnboundedContinuousVariable(
"x", 1));
551 ASSERT_NO_THROW(solver->addConstraint(
"", x <= solver->getConstant(12)));
552 ASSERT_NO_THROW(solver->optimize());
554 ASSERT_TRUE(solver->isOptimal());
555 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
558 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y"));
559 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(6)));
560 ASSERT_NO_THROW(solver->addConstraint(
"", x <= y));
562 ASSERT_NO_THROW(solver->optimize());
563 ASSERT_TRUE(solver->isOptimal());
564 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
565 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(y), this->precision());
567 ASSERT_NO_THROW(solver->optimize());
569 ASSERT_TRUE(solver->isOptimal());
570 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
572#ifdef STORM_HAVE_Z3_OPTIMIZE
573 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && !storm::test::z3AtLeastVersion(4, 8, 5)) {
574 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
579 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y", 10));
580 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(20)));
581 ASSERT_NO_THROW(solver->addConstraint(
"", y <= -x));
583 ASSERT_NO_THROW(solver->optimize());
584 ASSERT_TRUE(solver->isOptimal());
585 EXPECT_NEAR(this->
parseNumber(
"-20"), solver->getContinuousValue(x), this->precision());
586 EXPECT_NEAR(this->
parseNumber(
"20"), solver->getContinuousValue(y), this->precision());
589 ASSERT_NO_THROW(solver->optimize());
591 ASSERT_TRUE(solver->isOptimal());
592 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
595 ASSERT_NO_THROW(z = solver->addUnboundedIntegerVariable(
"z"));
596 ASSERT_NO_THROW(solver->addConstraint(
"", z <= solver->getConstant(6)));
597 ASSERT_NO_THROW(solver->addConstraint(
"", x <= z));
598 ASSERT_NO_THROW(solver->optimize());
600 ASSERT_TRUE(solver->isOptimal());
601 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
602 EXPECT_EQ(6, solver->getIntegerValue(z));
605 ASSERT_NO_THROW(solver->optimize());
607 ASSERT_TRUE(solver->isOptimal());
608 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
612 ASSERT_NO_THROW(solver->optimize());
613 ASSERT_FALSE(solver->isOptimal());
614 ASSERT_TRUE(solver->isUnbounded());
615 ASSERT_FALSE(solver->isInfeasible());
SFTBDDChecker::ValueType ValueType
NumberType parseNumber(std::string const &value)
Parse number from string.
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes
#define STORM_SILENT_ASSERT_THROW(statement, expected_exception)