1#include "storm-config.h"
16class DefaultEnvironment {
18 typedef double ValueType;
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 {
36 typedef double ValueType;
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;
66 typedef storm::RationalNumber ValueType;
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 {
127 ValueType
parseNumber(std::string
const& input)
const {
131 ValueType precision()
const {
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_SOPLEX
163 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());
398 if (this->solverSelection() == storm::solver::LpSolverTypeSelection::Z3 && storm::test::z3AtLeastVersion(4, 8, 8) &&
399 !storm::test::z3AtLeastVersion(4, 13, 3)) {
401 GTEST_SKIP() <<
"Test disabled since it triggers a bug in the installed version of z3.";
405 ASSERT_NO_THROW(solver->optimize());
406 ASSERT_TRUE(solver->isOptimal());
407 ASSERT_FALSE(solver->isUnbounded());
408 ASSERT_FALSE(solver->isInfeasible());
410 EXPECT_TRUE(solver->getBinaryValue(x));
411 EXPECT_EQ(0, solver->getIntegerValue(y));
412 EXPECT_NEAR(this->
parseNumber(
"5"), solver->getContinuousValue(z), this->precision());
413 EXPECT_NEAR(this->
parseNumber(
"-6"), solver->getObjectiveValue(), this->precision());
417 auto solver = this->factory()->create(
"");
418 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
422 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
423 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
424 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
425 ASSERT_NO_THROW(solver->update());
427 ASSERT_NO_THROW(solver->addConstraint(
"", x + y + z <= solver->getConstant(12)));
428 ASSERT_NO_THROW(solver->addConstraint(
"", solver->getConstant(this->parseNumber(
"1/2")) * y + z - x == solver->getConstant(5)));
429 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
430 if (this->supportsStrictRelation()) {
431 ASSERT_NO_THROW(solver->addConstraint(
"", y > solver->getConstant((this->parseNumber(
"7")))));
433 ASSERT_NO_THROW(solver->addConstraint(
"", y >= solver->getConstant(this->parseNumber(
"7") + this->precision())));
435 ASSERT_NO_THROW(solver->update());
437 ASSERT_NO_THROW(solver->optimize());
438 ASSERT_FALSE(solver->isOptimal());
439 ASSERT_FALSE(solver->isUnbounded());
440 ASSERT_TRUE(solver->isInfeasible());
448 if (!this->supportsInteger()) {
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 auto solver = this->factory()->create(
"");
483 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
487 ASSERT_NO_THROW(x = solver->addBoundedContinuousVariable(
"x", 0, 1, -1));
488 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
489 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
490 ASSERT_NO_THROW(solver->update());
492 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
493 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
494 ASSERT_NO_THROW(solver->update());
496 ASSERT_NO_THROW(solver->optimize());
497 ASSERT_FALSE(solver->isOptimal());
498 ASSERT_TRUE(solver->isUnbounded());
499 ASSERT_FALSE(solver->isInfeasible());
507 if (!this->supportsInteger()) {
510 auto solver = this->factory()->create(
"");
511 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
515 ASSERT_NO_THROW(x = solver->addBinaryVariable(
"x", -1));
516 ASSERT_NO_THROW(y = solver->addLowerBoundedContinuousVariable(
"y", 0, 2));
517 ASSERT_NO_THROW(z = solver->addLowerBoundedContinuousVariable(
"z", 0, 1));
518 ASSERT_NO_THROW(solver->update());
520 ASSERT_NO_THROW(solver->addConstraint(
"", x + y - z <= solver->getConstant(12)));
521 ASSERT_NO_THROW(solver->addConstraint(
"", y - x <= solver->getConstant(this->
parseNumber(
"11/2"))));
522 ASSERT_NO_THROW(solver->update());
524 ASSERT_NO_THROW(solver->optimize());
525 ASSERT_FALSE(solver->isOptimal());
526 ASSERT_TRUE(solver->isUnbounded());
527 ASSERT_FALSE(solver->isInfeasible());
535 if (!this->supportsIncremental()) {
538 auto solver = this->factory()->create(
"");
539 solver->setOptimizationDirection(storm::OptimizationDirection::Maximize);
541 ASSERT_NO_THROW(x = solver->addUnboundedContinuousVariable(
"x", 1));
544 ASSERT_NO_THROW(solver->addConstraint(
"", x <= solver->getConstant(12)));
545 ASSERT_NO_THROW(solver->optimize());
547 ASSERT_TRUE(solver->isOptimal());
548 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
551 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y"));
552 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(6)));
553 ASSERT_NO_THROW(solver->addConstraint(
"", x <= y));
555 ASSERT_NO_THROW(solver->optimize());
556 ASSERT_TRUE(solver->isOptimal());
557 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
558 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(y), this->precision());
560 ASSERT_NO_THROW(solver->optimize());
562 ASSERT_TRUE(solver->isOptimal());
563 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
566 ASSERT_NO_THROW(y = solver->addUnboundedContinuousVariable(
"y", 10));
567 ASSERT_NO_THROW(solver->addConstraint(
"", y <= solver->getConstant(20)));
568 ASSERT_NO_THROW(solver->addConstraint(
"", y <= -x));
570 ASSERT_NO_THROW(solver->optimize());
571 ASSERT_TRUE(solver->isOptimal());
572 EXPECT_NEAR(this->
parseNumber(
"-20"), solver->getContinuousValue(x), this->precision());
573 EXPECT_NEAR(this->
parseNumber(
"20"), solver->getContinuousValue(y), this->precision());
576 ASSERT_NO_THROW(solver->optimize());
578 ASSERT_TRUE(solver->isOptimal());
579 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
582 ASSERT_NO_THROW(z = solver->addUnboundedIntegerVariable(
"z"));
583 ASSERT_NO_THROW(solver->addConstraint(
"", z <= solver->getConstant(6)));
584 ASSERT_NO_THROW(solver->addConstraint(
"", x <= z));
585 ASSERT_NO_THROW(solver->optimize());
587 ASSERT_TRUE(solver->isOptimal());
588 EXPECT_NEAR(this->
parseNumber(
"6"), solver->getContinuousValue(x), this->precision());
589 EXPECT_EQ(6, solver->getIntegerValue(z));
592 ASSERT_NO_THROW(solver->optimize());
594 ASSERT_TRUE(solver->isOptimal());
595 EXPECT_NEAR(this->
parseNumber(
"12"), solver->getContinuousValue(x), this->precision());
599 ASSERT_NO_THROW(solver->optimize());
600 ASSERT_FALSE(solver->isOptimal());
601 ASSERT_TRUE(solver->isUnbounded());
602 ASSERT_FALSE(solver->isInfeasible());
SFTBDDChecker::ValueType ValueType
NumberType parseNumber(std::string const &value)
Parse number from string.
std::unique_ptr< LpSolverFactory< ValueType > > getLpSolverFactory(storm::solver::LpSolverTypeSelection solvType)
TargetType convertNumber(SourceType const &number)
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes
#define STORM_SILENT_ASSERT_THROW(statement, expected_exception)