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;
29class GlpkEnvironment {
32 static const bool isExact =
false;
33 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Glpk;
34 static const bool IntegerSupport =
true;
35 static const bool IncrementalSupport =
true;
36 static const bool strictRelationSupport =
true;
43#ifdef STORM_HAVE_GUROBI
44class GurobiEnvironment {
47 static const bool isExact =
false;
48 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Gurobi;
49 static const bool IntegerSupport =
true;
50 static const bool IncrementalSupport =
true;
51 static const bool strictRelationSupport =
true;
62 static const bool isExact =
true;
63 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Z3;
64 static const bool IntegerSupport =
true;
65 static const bool IncrementalSupport =
true;
66 static const bool strictRelationSupport =
true;
73#ifdef STORM_HAVE_SOPLEX
74class SoplexEnvironment {
77 static const bool isExact =
false;
78 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Soplex;
79 static const bool IntegerSupport =
false;
80 static const bool IncrementalSupport =
false;
81 static const bool strictRelationSupport =
false;
88class SoplexExactEnvironment {
91 static const bool isExact =
true;
92 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Soplex;
93 static const bool IntegerSupport =
false;
94 static const bool IncrementalSupport =
false;
95 static const bool strictRelationSupport =
false;
103template<
typename TestType>
104class LpSolverTest :
public ::testing::Test {
106 typedef typename TestType::ValueType
ValueType;
108 void SetUp()
override {
114 storm::solver::LpSolverTypeSelection solverSelection()
const {
115 return TestType::solverSelection;
118 std::unique_ptr<storm::utility::solver::LpSolverFactory<ValueType>> factory()
const {
119 return storm::utility::solver::getLpSolverFactory<ValueType>(solverSelection());
123 return storm::utility::convertNumber<ValueType>(input);
130 bool supportsInteger()
const {
131 return TestType::IntegerSupport;
134 bool supportsIncremental()
const {
135 return TestType::IncrementalSupport;
138 bool supportsStrictRelation()
const {
139 return TestType::strictRelationSupport;
142 bool skipped()
const {
143 return TestType::skip();
147typedef ::testing::Types<DefaultEnvironment
148#ifdef STORM_HAVE_GLPK
152#ifdef STORM_HAVE_GUROBI
156#ifdef STORM_HAVE_Z3_OPTIMIZE
160#ifdef STORM_HAVE_SOPLEX
162 SoplexEnvironment, SoplexExactEnvironment
170 typedef typename TestFixture::ValueType
ValueType;
171 auto solver = this->factory()->create(
"");
172 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
176 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
177 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
178 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
179 ASSERT_NO_THROW(solver->update());
181 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
182 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
183 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
184 ASSERT_NO_THROW(solver->update());
186 ASSERT_NO_THROW(solver->optimize());
187 ASSERT_TRUE(solver->isOptimal());
188 ASSERT_FALSE(solver->isUnbounded());
189 ASSERT_FALSE(solver->isInfeasible());
190 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(x), this->precision());
191 EXPECT_NEAR(this->
parseNumber(
"13/2"), solver->getContinuousValue(y), this->precision());
192 EXPECT_NEAR(this->
parseNumber(
"11/4"), solver->getContinuousValue(z), this->precision());
193 EXPECT_NEAR(this->
parseNumber(
"59/4"), solver->getObjectiveValue(), this->precision());
197 typedef typename TestFixture::ValueType
ValueType;
198 auto solver = this->factory()->createRaw(
"");
199 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
200 ASSERT_EQ(0u, solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
201 ASSERT_EQ(1u, solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
202 ASSERT_EQ(2u, solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
203 ASSERT_NO_THROW(solver->update());
210 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
216 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
221 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
222 ASSERT_NO_THROW(solver->update());
224 ASSERT_NO_THROW(solver->optimize());
225 ASSERT_TRUE(solver->isOptimal());
226 ASSERT_FALSE(solver->isUnbounded());
227 ASSERT_FALSE(solver->isInfeasible());
228 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(0), this->precision());
229 EXPECT_NEAR(this->
parseNumber(
"13/2"), solver->getContinuousValue(1), this->precision());
230 EXPECT_NEAR(this->
parseNumber(
"11/4"), solver->getContinuousValue(2), this->precision());
231 EXPECT_NEAR(this->
parseNumber(
"59/4"), solver->getObjectiveValue(), this->precision());
235 typedef typename TestFixture::ValueType
ValueType;
236 auto solver = this->factory()->create(
"");
237 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
241 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
242 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
243 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
244 ASSERT_NO_THROW(solver->update());
246 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
247 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
248 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
249 ASSERT_NO_THROW(solver->update());
251 ASSERT_NO_THROW(solver->optimize());
252 ASSERT_TRUE(solver->isOptimal());
253 ASSERT_FALSE(solver->isUnbounded());
254 ASSERT_FALSE(solver->isInfeasible());
256 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(x), this->precision());
257 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(y), this->precision());
258 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(z), this->precision());
259 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
263 typedef typename TestFixture::ValueType
ValueType;
264 auto solver = this->factory()->createRaw(
"");
265 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
267 ASSERT_EQ(0u, solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
268 ASSERT_EQ(1u, solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
269 ASSERT_EQ(2u, solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
270 ASSERT_NO_THROW(solver->update());
277 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
283 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
288 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
289 ASSERT_NO_THROW(solver->update());
291 ASSERT_NO_THROW(solver->optimize());
292 ASSERT_TRUE(solver->isOptimal());
293 ASSERT_FALSE(solver->isUnbounded());
294 ASSERT_FALSE(solver->isInfeasible());
296 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(0), this->precision());
297 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(1), this->precision());
298 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(2), this->precision());
299 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
303 if (!this->supportsInteger()) {
306 typedef typename TestFixture::ValueType
ValueType;
307 auto solver = this->factory()->create(
"");
308 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
312 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
313 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
314 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
315 ASSERT_NO_THROW(solver->update());
317 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
318 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
319 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
320 ASSERT_NO_THROW(solver->update());
321 ASSERT_NO_THROW(solver->optimize());
322 ASSERT_TRUE(solver->isOptimal());
323 ASSERT_FALSE(solver->isUnbounded());
324 ASSERT_FALSE(solver->isInfeasible());
326 EXPECT_TRUE(solver->getBinaryValue(x));
327 EXPECT_EQ(6, solver->getIntegerValue(y));
328 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(z), this->precision());
329 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
333 if (!this->supportsInteger()) {
336 typedef typename TestFixture::ValueType
ValueType;
337 auto solver = this->factory()->createRaw(
"");
338 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
342 ASSERT_EQ(0u, solver->addBinaryVariable(
"x", -1));
343 ASSERT_EQ(1u, solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
344 ASSERT_EQ(2u, solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
345 ASSERT_NO_THROW(solver->update());
352 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
358 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
363 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
364 ASSERT_NO_THROW(solver->update());
366 ASSERT_NO_THROW(solver->optimize());
367 ASSERT_TRUE(solver->isOptimal());
368 ASSERT_FALSE(solver->isUnbounded());
369 ASSERT_FALSE(solver->isInfeasible());
370 EXPECT_TRUE(solver->getBinaryValue(0));
371 EXPECT_EQ(6, solver->getIntegerValue(1));
372 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(2), this->precision());
373 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
377 if (!this->supportsInteger()) {
380 typedef typename TestFixture::ValueType
ValueType;
381 auto solver = this->factory()->create(
"");
382 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
386 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
387 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
388 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 0, 5, -1));
389 ASSERT_NO_THROW(solver->update());
391 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
392 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
393 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
394 ASSERT_NO_THROW(solver->update());
396#ifdef STORM_HAVE_Z3_OPTIMIZE
397 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && storm::test::z3AtLeastVersion(4, 8, 8)) {
399 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
403 ASSERT_NO_THROW(solver->optimize());
404 ASSERT_TRUE(solver->isOptimal());
405 ASSERT_FALSE(solver->isUnbounded());
406 ASSERT_FALSE(solver->isInfeasible());
408 EXPECT_TRUE(solver->getBinaryValue(x));
409 EXPECT_EQ(0, solver->getIntegerValue(y));
410 EXPECT_NEAR(this->
parseNumber(
"5"), solver->getContinuousValue(z), this->precision());
411 EXPECT_NEAR(this->
parseNumber(
"-6"), solver->getObjectiveValue(), this->precision());
415 typedef typename TestFixture::ValueType
ValueType;
416 auto solver = this->factory()->create(
"");
417 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
421 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
422 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
423 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
424 ASSERT_NO_THROW(solver->update());
426 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
427 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
428 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
429 if (this->supportsStrictRelation()) {
430 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
432 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
434 ASSERT_NO_THROW(solver->update());
436 ASSERT_NO_THROW(solver->optimize());
437 ASSERT_FALSE(solver->isOptimal());
438 ASSERT_FALSE(solver->isUnbounded());
439 ASSERT_TRUE(solver->isInfeasible());
447 if (!this->supportsInteger()) {
450 typedef typename TestFixture::ValueType
ValueType;
451 auto solver = this->factory()->create(
"");
452 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
456 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
457 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
458 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
459 ASSERT_NO_THROW(solver->update());
461 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
462 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
463 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
464 if (this->supportsStrictRelation()) {
465 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
467 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
469 ASSERT_NO_THROW(solver->update());
471 ASSERT_NO_THROW(solver->optimize());
472 ASSERT_FALSE(solver->isOptimal());
473 ASSERT_FALSE(solver->isUnbounded());
474 ASSERT_TRUE(solver->isInfeasible());
482 typedef typename TestFixture::ValueType
ValueType;
483 auto solver = this->factory()->create(
"");
484 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
488 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
489 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
490 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
491 ASSERT_NO_THROW(solver->update());
493 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
494 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
495 ASSERT_NO_THROW(solver->update());
497 ASSERT_NO_THROW(solver->optimize());
498 ASSERT_FALSE(solver->isOptimal());
499 ASSERT_TRUE(solver->isUnbounded());
500 ASSERT_FALSE(solver->isInfeasible());
508 if (!this->supportsInteger()) {
511 typedef typename TestFixture::ValueType
ValueType;
512 auto solver = this->factory()->create(
"");
513 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
517 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
518 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
519 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
520 ASSERT_NO_THROW(solver->update());
522 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
523 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
524 ASSERT_NO_THROW(solver->update());
526 ASSERT_NO_THROW(solver->optimize());
527 ASSERT_FALSE(solver->isOptimal());
528 ASSERT_TRUE(solver->isUnbounded());
529 ASSERT_FALSE(solver->isInfeasible());
537 if (!this->supportsIncremental()) {
540 typedef typename TestFixture::ValueType
ValueType;
541 auto solver = this->factory()->create(
"");
542 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
544 ASSERT_NO_THROW(x = solver->addUnboundedContinuousVariable(
"x", 1));
547 ASSERT_NO_THROW(solver->addConstraint(
"", x <= solver->getConstant(12)));
548 ASSERT_NO_THROW(solver->optimize());
550 ASSERT_TRUE(solver->isOptimal());
551 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
554 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y"));
555 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(6)));
556 ASSERT_NO_THROW(solver->addConstraint(
"", x <= y));
558 ASSERT_NO_THROW(solver->optimize());
559 ASSERT_TRUE(solver->isOptimal());
560 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
561 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(y), this->precision());
563 ASSERT_NO_THROW(solver->optimize());
565 ASSERT_TRUE(solver->isOptimal());
566 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
568#ifdef STORM_HAVE_Z3_OPTIMIZE
569 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && !storm::test::z3AtLeastVersion(4, 8, 5)) {
570 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
575 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y", 10));
576 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(20)));
577 ASSERT_NO_THROW(solver->addConstraint(
"", y <= -x));
579 ASSERT_NO_THROW(solver->optimize());
580 ASSERT_TRUE(solver->isOptimal());
581 EXPECT_NEAR(this->
parseNumber(
"-20"), solver->getContinuousValue(x), this->precision());
582 EXPECT_NEAR(this->
parseNumber(
"20"), solver->getContinuousValue(y), this->precision());
585 ASSERT_NO_THROW(solver->optimize());
587 ASSERT_TRUE(solver->isOptimal());
588 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
591 ASSERT_NO_THROW(z = solver->addUnboundedIntegerVariable(
"z"));
592 ASSERT_NO_THROW(solver->addConstraint(
"", z <= solver->getConstant(6)));
593 ASSERT_NO_THROW(solver->addConstraint(
"", x <= z));
594 ASSERT_NO_THROW(solver->optimize());
596 ASSERT_TRUE(solver->isOptimal());
597 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
598 EXPECT_EQ(6, solver->getIntegerValue(z));
601 ASSERT_NO_THROW(solver->optimize());
603 ASSERT_TRUE(solver->isOptimal());
604 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
608 ASSERT_NO_THROW(solver->optimize());
609 ASSERT_FALSE(solver->isOptimal());
610 ASSERT_TRUE(solver->isUnbounded());
611 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)