1#include "storm-config.h"
16class DefaultEnvironment {
19 static const bool isExact =
false;
20 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::FROMSETTINGS;
21 static const bool IntegerSupport =
true;
22 static const bool IncrementalSupport =
true;
23 static const bool strictRelationSupport =
true;
26#ifdef STORM_HAVE_LP_SOLVER
34class GlpkEnvironment {
37 static const bool isExact =
false;
38 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Glpk;
39 static const bool IntegerSupport =
true;
40 static const bool IncrementalSupport =
true;
41 static const bool strictRelationSupport =
true;
48#ifdef STORM_HAVE_GUROBI
49class GurobiEnvironment {
52 static const bool isExact =
false;
53 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Gurobi;
54 static const bool IntegerSupport =
true;
55 static const bool IncrementalSupport =
true;
56 static const bool strictRelationSupport =
true;
67 static const bool isExact =
true;
68 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Z3;
69 static const bool IntegerSupport =
true;
70 static const bool IncrementalSupport =
true;
71 static const bool strictRelationSupport =
true;
78#ifdef STORM_HAVE_SOPLEX
79class SoplexEnvironment {
82 static const bool isExact =
false;
83 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Soplex;
84 static const bool IntegerSupport =
false;
85 static const bool IncrementalSupport =
false;
86 static const bool strictRelationSupport =
false;
93class SoplexExactEnvironment {
96 static const bool isExact =
true;
97 static const storm::solver::LpSolverTypeSelection solverSelection = storm::solver::LpSolverTypeSelection::Soplex;
98 static const bool IntegerSupport =
false;
99 static const bool IncrementalSupport =
false;
100 static const bool strictRelationSupport =
false;
108template<
typename TestType>
109class LpSolverTest :
public ::testing::Test {
111 typedef typename TestType::ValueType
ValueType;
113 void SetUp()
override {
119 storm::solver::LpSolverTypeSelection solverSelection()
const {
120 return TestType::solverSelection;
123 std::unique_ptr<storm::utility::solver::LpSolverFactory<ValueType>> factory()
const {
124 return storm::utility::solver::getLpSolverFactory<ValueType>(solverSelection());
128 return storm::utility::convertNumber<ValueType>(input);
135 bool supportsInteger()
const {
136 return TestType::IntegerSupport;
139 bool supportsIncremental()
const {
140 return TestType::IncrementalSupport;
143 bool supportsStrictRelation()
const {
144 return TestType::strictRelationSupport;
147 bool skipped()
const {
148 return TestType::skip();
152typedef ::testing::Types<DefaultEnvironment
153#ifdef STORM_HAVE_GLPK
157#ifdef STORM_HAVE_GUROBI
161#ifdef STORM_HAVE_Z3_OPTIMIZE
165#ifdef STORM_HAVE_SOPLEX
167 SoplexEnvironment, SoplexExactEnvironment
175 typedef typename TestFixture::ValueType
ValueType;
176 auto solver = this->factory()->create(
"");
177 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
181 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
182 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
183 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
184 ASSERT_NO_THROW(solver->update());
186 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
187 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
188 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
189 ASSERT_NO_THROW(solver->update());
191 ASSERT_NO_THROW(solver->optimize());
192 ASSERT_TRUE(solver->isOptimal());
193 ASSERT_FALSE(solver->isUnbounded());
194 ASSERT_FALSE(solver->isInfeasible());
195 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(x), this->precision());
196 EXPECT_NEAR(this->
parseNumber(
"13/2"), solver->getContinuousValue(y), this->precision());
197 EXPECT_NEAR(this->
parseNumber(
"11/4"), solver->getContinuousValue(z), this->precision());
198 EXPECT_NEAR(this->
parseNumber(
"59/4"), solver->getObjectiveValue(), this->precision());
202 typedef typename TestFixture::ValueType
ValueType;
203 auto solver = this->factory()->createRaw(
"");
204 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
205 ASSERT_EQ(0u, solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
206 ASSERT_EQ(1u, solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
207 ASSERT_EQ(2u, solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
208 ASSERT_NO_THROW(solver->update());
215 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
221 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
226 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
227 ASSERT_NO_THROW(solver->update());
229 ASSERT_NO_THROW(solver->optimize());
230 ASSERT_TRUE(solver->isOptimal());
231 ASSERT_FALSE(solver->isUnbounded());
232 ASSERT_FALSE(solver->isInfeasible());
233 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(0), this->precision());
234 EXPECT_NEAR(this->
parseNumber(
"13/2"), solver->getContinuousValue(1), this->precision());
235 EXPECT_NEAR(this->
parseNumber(
"11/4"), solver->getContinuousValue(2), this->precision());
236 EXPECT_NEAR(this->
parseNumber(
"59/4"), solver->getObjectiveValue(), this->precision());
240 typedef typename TestFixture::ValueType
ValueType;
241 auto solver = this->factory()->create(
"");
242 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
246 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
247 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
248 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
249 ASSERT_NO_THROW(solver->update());
251 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
252 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
253 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
254 ASSERT_NO_THROW(solver->update());
256 ASSERT_NO_THROW(solver->optimize());
257 ASSERT_TRUE(solver->isOptimal());
258 ASSERT_FALSE(solver->isUnbounded());
259 ASSERT_FALSE(solver->isInfeasible());
261 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(x), this->precision());
262 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(y), this->precision());
263 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(z), this->precision());
264 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
268 typedef typename TestFixture::ValueType
ValueType;
269 auto solver = this->factory()->createRaw(
"");
270 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
272 ASSERT_EQ(0u, solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
273 ASSERT_EQ(1u, solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
274 ASSERT_EQ(2u, solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
275 ASSERT_NO_THROW(solver->update());
282 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
288 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
293 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
294 ASSERT_NO_THROW(solver->update());
296 ASSERT_NO_THROW(solver->optimize());
297 ASSERT_TRUE(solver->isOptimal());
298 ASSERT_FALSE(solver->isUnbounded());
299 ASSERT_FALSE(solver->isInfeasible());
301 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(0), this->precision());
302 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(1), this->precision());
303 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(2), this->precision());
304 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
308 if (!this->supportsInteger()) {
311 typedef typename TestFixture::ValueType
ValueType;
312 auto solver = this->factory()->create(
"");
313 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
317 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
318 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
319 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
320 ASSERT_NO_THROW(solver->update());
322 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
323 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
324 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
325 ASSERT_NO_THROW(solver->update());
326 ASSERT_NO_THROW(solver->optimize());
327 ASSERT_TRUE(solver->isOptimal());
328 ASSERT_FALSE(solver->isUnbounded());
329 ASSERT_FALSE(solver->isInfeasible());
331 EXPECT_TRUE(solver->getBinaryValue(x));
332 EXPECT_EQ(6, solver->getIntegerValue(y));
333 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(z), this->precision());
334 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
338 if (!this->supportsInteger()) {
341 typedef typename TestFixture::ValueType
ValueType;
342 auto solver = this->factory()->createRaw(
"");
343 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
347 ASSERT_EQ(0u, solver->addBinaryVariable(
"x", -1));
348 ASSERT_EQ(1u, solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
349 ASSERT_EQ(2u, solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
350 ASSERT_NO_THROW(solver->update());
357 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
363 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
368 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
369 ASSERT_NO_THROW(solver->update());
371 ASSERT_NO_THROW(solver->optimize());
372 ASSERT_TRUE(solver->isOptimal());
373 ASSERT_FALSE(solver->isUnbounded());
374 ASSERT_FALSE(solver->isInfeasible());
375 EXPECT_TRUE(solver->getBinaryValue(0));
376 EXPECT_EQ(6, solver->getIntegerValue(1));
377 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(2), this->precision());
378 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
382 if (!this->supportsInteger()) {
385 typedef typename TestFixture::ValueType
ValueType;
386 auto solver = this->factory()->create(
"");
387 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
391 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
392 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
393 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 0, 5, -1));
394 ASSERT_NO_THROW(solver->update());
396 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
397 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
398 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
399 ASSERT_NO_THROW(solver->update());
401#ifdef STORM_HAVE_Z3_OPTIMIZE
402 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && storm::test::z3AtLeastVersion(4, 8, 8)) {
404 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
408 ASSERT_NO_THROW(solver->optimize());
409 ASSERT_TRUE(solver->isOptimal());
410 ASSERT_FALSE(solver->isUnbounded());
411 ASSERT_FALSE(solver->isInfeasible());
413 EXPECT_TRUE(solver->getBinaryValue(x));
414 EXPECT_EQ(0, solver->getIntegerValue(y));
415 EXPECT_NEAR(this->
parseNumber(
"5"), solver->getContinuousValue(z), this->precision());
416 EXPECT_NEAR(this->
parseNumber(
"-6"), solver->getObjectiveValue(), this->precision());
420 typedef typename TestFixture::ValueType
ValueType;
421 auto solver = this->factory()->create(
"");
422 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
426 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
427 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
428 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
429 ASSERT_NO_THROW(solver->update());
431 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
432 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
433 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
434 if (this->supportsStrictRelation()) {
435 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
437 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
439 ASSERT_NO_THROW(solver->update());
441 ASSERT_NO_THROW(solver->optimize());
442 ASSERT_FALSE(solver->isOptimal());
443 ASSERT_FALSE(solver->isUnbounded());
444 ASSERT_TRUE(solver->isInfeasible());
452 if (!this->supportsInteger()) {
455 typedef typename TestFixture::ValueType
ValueType;
456 auto solver = this->factory()->create(
"");
457 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
461 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
462 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
463 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
464 ASSERT_NO_THROW(solver->update());
466 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
467 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
468 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
469 if (this->supportsStrictRelation()) {
470 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
472 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
474 ASSERT_NO_THROW(solver->update());
476 ASSERT_NO_THROW(solver->optimize());
477 ASSERT_FALSE(solver->isOptimal());
478 ASSERT_FALSE(solver->isUnbounded());
479 ASSERT_TRUE(solver->isInfeasible());
487 typedef typename TestFixture::ValueType
ValueType;
488 auto solver = this->factory()->create(
"");
489 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
493 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
494 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
495 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
496 ASSERT_NO_THROW(solver->update());
498 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
499 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
500 ASSERT_NO_THROW(solver->update());
502 ASSERT_NO_THROW(solver->optimize());
503 ASSERT_FALSE(solver->isOptimal());
504 ASSERT_TRUE(solver->isUnbounded());
505 ASSERT_FALSE(solver->isInfeasible());
513 if (!this->supportsInteger()) {
516 typedef typename TestFixture::ValueType
ValueType;
517 auto solver = this->factory()->create(
"");
518 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
522 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
523 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
524 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
525 ASSERT_NO_THROW(solver->update());
527 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
528 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
529 ASSERT_NO_THROW(solver->update());
531 ASSERT_NO_THROW(solver->optimize());
532 ASSERT_FALSE(solver->isOptimal());
533 ASSERT_TRUE(solver->isUnbounded());
534 ASSERT_FALSE(solver->isInfeasible());
542 if (!this->supportsIncremental()) {
545 typedef typename TestFixture::ValueType
ValueType;
546 auto solver = this->factory()->create(
"");
547 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
549 ASSERT_NO_THROW(x = solver->addUnboundedContinuousVariable(
"x", 1));
552 ASSERT_NO_THROW(solver->addConstraint(
"", x <= solver->getConstant(12)));
553 ASSERT_NO_THROW(solver->optimize());
555 ASSERT_TRUE(solver->isOptimal());
556 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
559 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y"));
560 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(6)));
561 ASSERT_NO_THROW(solver->addConstraint(
"", x <= y));
563 ASSERT_NO_THROW(solver->optimize());
564 ASSERT_TRUE(solver->isOptimal());
565 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
566 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(y), this->precision());
568 ASSERT_NO_THROW(solver->optimize());
570 ASSERT_TRUE(solver->isOptimal());
571 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
573#ifdef STORM_HAVE_Z3_OPTIMIZE
574 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && !storm::test::z3AtLeastVersion(4, 8, 5)) {
575 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
580 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y", 10));
581 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(20)));
582 ASSERT_NO_THROW(solver->addConstraint(
"", y <= -x));
584 ASSERT_NO_THROW(solver->optimize());
585 ASSERT_TRUE(solver->isOptimal());
586 EXPECT_NEAR(this->
parseNumber(
"-20"), solver->getContinuousValue(x), this->precision());
587 EXPECT_NEAR(this->
parseNumber(
"20"), solver->getContinuousValue(y), this->precision());
590 ASSERT_NO_THROW(solver->optimize());
592 ASSERT_TRUE(solver->isOptimal());
593 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
596 ASSERT_NO_THROW(z = solver->addUnboundedIntegerVariable(
"z"));
597 ASSERT_NO_THROW(solver->addConstraint(
"", z <= solver->getConstant(6)));
598 ASSERT_NO_THROW(solver->addConstraint(
"", x <= z));
599 ASSERT_NO_THROW(solver->optimize());
601 ASSERT_TRUE(solver->isOptimal());
602 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
603 EXPECT_EQ(6, solver->getIntegerValue(z));
606 ASSERT_NO_THROW(solver->optimize());
608 ASSERT_TRUE(solver->isOptimal());
609 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
613 ASSERT_NO_THROW(solver->optimize());
614 ASSERT_FALSE(solver->isOptimal());
615 ASSERT_TRUE(solver->isUnbounded());
616 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)