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 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 auto solver = this->factory()->create(
"");
240 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
244 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
245 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
246 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
247 ASSERT_NO_THROW(solver->update());
249 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
250 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
251 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
252 ASSERT_NO_THROW(solver->update());
254 ASSERT_NO_THROW(solver->optimize());
255 ASSERT_TRUE(solver->isOptimal());
256 ASSERT_FALSE(solver->isUnbounded());
257 ASSERT_FALSE(solver->isInfeasible());
259 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(x), this->precision());
260 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(y), this->precision());
261 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(z), this->precision());
262 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
266 typedef typename TestFixture::ValueType
ValueType;
267 auto solver = this->factory()->createRaw(
"");
268 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
270 ASSERT_EQ(0u, solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
271 ASSERT_EQ(1u, solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
272 ASSERT_EQ(2u, solver->addBoundedContinuousVariable(
"z", 1, this->parseNumber(
"57/10"), -1));
273 ASSERT_NO_THROW(solver->update());
280 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
286 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
291 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
292 ASSERT_NO_THROW(solver->update());
294 ASSERT_NO_THROW(solver->optimize());
295 ASSERT_TRUE(solver->isOptimal());
296 ASSERT_FALSE(solver->isUnbounded());
297 ASSERT_FALSE(solver->isInfeasible());
299 EXPECT_NEAR(this->
parseNumber(
"1"), solver->getContinuousValue(0), this->precision());
300 EXPECT_NEAR(this->
parseNumber(
"0"), solver->getContinuousValue(1), this->precision());
301 EXPECT_NEAR(this->
parseNumber(
"57/10"), solver->getContinuousValue(2), this->precision());
302 EXPECT_NEAR(this->
parseNumber(
"-67/10"), solver->getObjectiveValue(), this->precision());
306 if (!this->supportsInteger()) {
309 auto solver = this->factory()->create(
"");
310 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
314 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
315 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
316 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
317 ASSERT_NO_THROW(solver->update());
319 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
320 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
321 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
322 ASSERT_NO_THROW(solver->update());
323 ASSERT_NO_THROW(solver->optimize());
324 ASSERT_TRUE(solver->isOptimal());
325 ASSERT_FALSE(solver->isUnbounded());
326 ASSERT_FALSE(solver->isInfeasible());
328 EXPECT_TRUE(solver->getBinaryValue(x));
329 EXPECT_EQ(6, solver->getIntegerValue(y));
330 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(z), this->precision());
331 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
335 if (!this->supportsInteger()) {
338 typedef typename TestFixture::ValueType
ValueType;
339 auto solver = this->factory()->createRaw(
"");
340 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
344 ASSERT_EQ(0u, solver->addBinaryVariable(
"x", -1));
345 ASSERT_EQ(1u, solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
346 ASSERT_EQ(2u, solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
347 ASSERT_NO_THROW(solver->update());
354 ASSERT_NO_THROW(solver->addConstraint(
"", constraint1));
360 ASSERT_NO_THROW(solver->addConstraint(
"", constraint2));
365 ASSERT_NO_THROW(solver->addConstraint(
"", constraint3));
366 ASSERT_NO_THROW(solver->update());
368 ASSERT_NO_THROW(solver->optimize());
369 ASSERT_TRUE(solver->isOptimal());
370 ASSERT_FALSE(solver->isUnbounded());
371 ASSERT_FALSE(solver->isInfeasible());
372 EXPECT_TRUE(solver->getBinaryValue(0));
373 EXPECT_EQ(6, solver->getIntegerValue(1));
374 EXPECT_NEAR(this->
parseNumber(
"3"), solver->getContinuousValue(2), this->precision());
375 EXPECT_NEAR(this->
parseNumber(
"14"), solver->getObjectiveValue(), this->precision());
379 if (!this->supportsInteger()) {
382 auto solver = this->factory()->create(
"");
383 solver->setOptimizationDirection(storm::OptimizationDirection::Minimize);
387 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
388 ASSERT_NO_THROW(y = solver->addLowerBoundedIntegerVariable(
"y", 0, 2));
389 ASSERT_NO_THROW(z = solver->addBoundedContinuousVariable(
"z", 0, 5, -1));
390 ASSERT_NO_THROW(solver->update());
392 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
393 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x <= solver->getConstant(5)));
394 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
395 ASSERT_NO_THROW(solver->update());
397#ifdef STORM_HAVE_Z3_OPTIMIZE
398 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && storm::test::z3AtLeastVersion(4, 8, 8)) {
400 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
404 ASSERT_NO_THROW(solver->optimize());
405 ASSERT_TRUE(solver->isOptimal());
406 ASSERT_FALSE(solver->isUnbounded());
407 ASSERT_FALSE(solver->isInfeasible());
409 EXPECT_TRUE(solver->getBinaryValue(x));
410 EXPECT_EQ(0, solver->getIntegerValue(y));
411 EXPECT_NEAR(this->
parseNumber(
"5"), solver->getContinuousValue(z), this->precision());
412 EXPECT_NEAR(this->
parseNumber(
"-6"), solver->getObjectiveValue(), this->precision());
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 auto solver = this->factory()->create(
"");
451 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
455 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
456 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
457 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
458 ASSERT_NO_THROW(solver->update());
460 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
461 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
462 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
463 if (this->supportsStrictRelation()) {
464 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
466 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
468 ASSERT_NO_THROW(solver->update());
470 ASSERT_NO_THROW(solver->optimize());
471 ASSERT_FALSE(solver->isOptimal());
472 ASSERT_FALSE(solver->isUnbounded());
473 ASSERT_TRUE(solver->isInfeasible());
481 auto solver = this->factory()->create(
"");
482 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
486 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
487 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
488 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
489 ASSERT_NO_THROW(solver->update());
491 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
492 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
493 ASSERT_NO_THROW(solver->update());
495 ASSERT_NO_THROW(solver->optimize());
496 ASSERT_FALSE(solver->isOptimal());
497 ASSERT_TRUE(solver->isUnbounded());
498 ASSERT_FALSE(solver->isInfeasible());
506 if (!this->supportsInteger()) {
509 auto solver = this->factory()->create(
"");
510 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
514 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
515 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
516 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
517 ASSERT_NO_THROW(solver->update());
519 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
520 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
521 ASSERT_NO_THROW(solver->update());
523 ASSERT_NO_THROW(solver->optimize());
524 ASSERT_FALSE(solver->isOptimal());
525 ASSERT_TRUE(solver->isUnbounded());
526 ASSERT_FALSE(solver->isInfeasible());
534 if (!this->supportsIncremental()) {
537 auto solver = this->factory()->create(
"");
538 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
540 ASSERT_NO_THROW(x = solver->addUnboundedContinuousVariable(
"x", 1));
543 ASSERT_NO_THROW(solver->addConstraint(
"", x <= solver->getConstant(12)));
544 ASSERT_NO_THROW(solver->optimize());
546 ASSERT_TRUE(solver->isOptimal());
547 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
550 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y"));
551 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(6)));
552 ASSERT_NO_THROW(solver->addConstraint(
"", x <= y));
554 ASSERT_NO_THROW(solver->optimize());
555 ASSERT_TRUE(solver->isOptimal());
556 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
557 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(y), this->precision());
559 ASSERT_NO_THROW(solver->optimize());
561 ASSERT_TRUE(solver->isOptimal());
562 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
564#ifdef STORM_HAVE_Z3_OPTIMIZE
565 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && !storm::test::z3AtLeastVersion(4, 8, 5)) {
566 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
571 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y", 10));
572 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(20)));
573 ASSERT_NO_THROW(solver->addConstraint(
"", y <= -x));
575 ASSERT_NO_THROW(solver->optimize());
576 ASSERT_TRUE(solver->isOptimal());
577 EXPECT_NEAR(this->
parseNumber(
"-20"), solver->getContinuousValue(x), this->precision());
578 EXPECT_NEAR(this->
parseNumber(
"20"), solver->getContinuousValue(y), this->precision());
581 ASSERT_NO_THROW(solver->optimize());
583 ASSERT_TRUE(solver->isOptimal());
584 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
587 ASSERT_NO_THROW(z = solver->addUnboundedIntegerVariable(
"z"));
588 ASSERT_NO_THROW(solver->addConstraint(
"", z <= solver->getConstant(6)));
589 ASSERT_NO_THROW(solver->addConstraint(
"", x <= z));
590 ASSERT_NO_THROW(solver->optimize());
592 ASSERT_TRUE(solver->isOptimal());
593 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
594 EXPECT_EQ(6, solver->getIntegerValue(z));
597 ASSERT_NO_THROW(solver->optimize());
599 ASSERT_TRUE(solver->isOptimal());
600 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
604 ASSERT_NO_THROW(solver->optimize());
605 ASSERT_FALSE(solver->isOptimal());
606 ASSERT_TRUE(solver->isUnbounded());
607 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)