Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
MinMaxLinearEquationSolverTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
11
12namespace {
13
14class DoubleViEnvironment {
15 public:
16 typedef double ValueType;
17 static const bool isExact = false;
18 static const bool reportsBounds = false;
19 static storm::Environment createEnvironment() {
20 storm::Environment env;
21 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration);
23 return env;
24 }
25};
26
27class DoubleViRegMultEnvironment {
28 public:
29 typedef double ValueType;
30 static const bool isExact = false;
31 static const bool reportsBounds = false;
32 static storm::Environment createEnvironment() {
33 storm::Environment env;
34 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration);
37 return env;
38 }
39};
40
41class DoubleSoundViEnvironment {
42 public:
43 typedef double ValueType;
44 static const bool isExact = false;
45 static const bool reportsBounds = true;
46 static storm::Environment createEnvironment() {
47 storm::Environment env;
48 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::SoundValueIteration);
49 env.solver().setForceSoundness(true);
51 return env;
52 }
53};
54
55class DoubleIntervalIterationEnvironment {
56 public:
57 typedef double ValueType;
58 static const bool isExact = false;
59 static const bool reportsBounds = true;
60 static storm::Environment createEnvironment() {
61 storm::Environment env;
62 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::IntervalIteration);
63 env.solver().setForceSoundness(true);
65 return env;
66 }
67};
68
69class DoubleGuessingViEnvironment {
70 public:
71 typedef double ValueType;
72 static const bool isExact = false;
73 static const bool reportsBounds = true;
74 static storm::Environment createEnvironment() {
75 storm::Environment env;
76 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::GuessingValueIteration);
77 env.solver().setForceSoundness(true);
79 return env;
80 }
81};
82
83class DoubleOptimisticViEnvironment {
84 public:
85 typedef double ValueType;
86 static const bool isExact = false;
87 static const bool reportsBounds = true;
88 static storm::Environment createEnvironment() {
89 storm::Environment env;
90 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::OptimisticValueIteration);
91 env.solver().setForceSoundness(true);
93 return env;
94 }
95};
96
97class DoubleTopologicalViEnvironment {
98 public:
99 typedef double ValueType;
100 static const bool isExact = false;
101 static const bool reportsBounds = true;
102 static storm::Environment createEnvironment() {
103 storm::Environment env;
104 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::Topological);
105 env.solver().topological().setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod::ValueIteration);
107 return env;
108 }
109};
110
111class DoublePIEnvironment {
112 public:
113 typedef double ValueType;
114 static const bool isExact = false;
115 static const bool reportsBounds = false;
116 static storm::Environment createEnvironment() {
117 storm::Environment env;
118 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration);
120 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
121 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Jacobi);
123 return env;
124 }
125};
126class RationalPIEnvironment {
127 public:
128 typedef storm::RationalNumber ValueType;
129 static const bool isExact = true;
130 static const bool reportsBounds = true;
131 static storm::Environment createEnvironment() {
132 storm::Environment env;
133 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration);
134 return env;
135 }
136};
137class RationalRationalSearchEnvironment {
138 public:
139 typedef storm::RationalNumber ValueType;
140 static const bool isExact = true;
141 static const bool reportsBounds = true;
142 static storm::Environment createEnvironment() {
143 storm::Environment env;
144 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::RationalSearch);
145 return env;
146 }
147};
148
149template<typename TestType>
150class MinMaxLinearEquationSolverTest : public ::testing::Test {
151 public:
152 typedef typename TestType::ValueType ValueType;
153 MinMaxLinearEquationSolverTest() : _environment(TestType::createEnvironment()) {}
154 storm::Environment const& env() const {
155 return _environment;
156 }
157 ValueType precision() const {
158 return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");
159 }
160 ValueType parseNumber(std::string const& input) const {
162 }
163 bool reportsBounds() const {
164 return TestType::reportsBounds;
165 }
166
170 void expectSolutionBoundsEnclose(storm::solver::MinMaxLinearEquationSolver<ValueType> const& solver, uint64_t index, ValueType const& value) const {
171 ASSERT_TRUE(solver.hasSolutionLowerBounds()) << "No lower bound on the solution was reported.";
172 ASSERT_TRUE(solver.hasSolutionUpperBounds()) << "No upper bound on the solution was reported.";
173 EXPECT_LE(solver.getSolutionLowerBounds()[index], value + precision()) << "The lower bound exceeds the solution.";
174 EXPECT_LE(value, solver.getSolutionUpperBounds()[index] + precision()) << "The upper bound falls below the solution.";
175 }
176
177 private:
178 storm::Environment _environment;
179};
180
181typedef ::testing::Types<DoubleViEnvironment, DoubleViRegMultEnvironment, DoubleSoundViEnvironment, DoubleIntervalIterationEnvironment,
182 DoubleOptimisticViEnvironment, DoubleGuessingViEnvironment, DoubleTopologicalViEnvironment, DoublePIEnvironment, RationalPIEnvironment,
183 RationalRationalSearchEnvironment>
185
186TYPED_TEST_SUITE(MinMaxLinearEquationSolverTest, TestingTypes, );
187
188TYPED_TEST(MinMaxLinearEquationSolverTest, SolveEquations) {
189 typedef typename TestFixture::ValueType ValueType;
190
191 storm::storage::SparseMatrixBuilder<ValueType> builder(0, 0, 0, false, true);
192 ASSERT_NO_THROW(builder.newRowGroup(0));
193 ASSERT_NO_THROW(builder.addNextValue(0, 0, this->parseNumber("0.9")));
194
196 ASSERT_NO_THROW(A = builder.build(2));
197
198 std::vector<ValueType> x(1);
199 std::vector<ValueType> b = {this->parseNumber("0.099"), this->parseNumber("0.5")};
200
202 auto solver = factory.create(this->env(), A);
203 solver->setHasUniqueSolution(true);
204 solver->setHasNoEndComponents(true);
205 solver->setBounds(this->parseNumber("0"), this->parseNumber("2"));
207 req.clearBounds();
208 ASSERT_FALSE(req.hasEnabledRequirement());
209 ASSERT_NO_THROW(solver->solveEquations(this->env(), storm::OptimizationDirection::Minimize, x, b));
210 EXPECT_NEAR(x[0], this->parseNumber("0.5"), this->precision());
211 if (this->reportsBounds()) {
212 this->expectSolutionBoundsEnclose(*solver, 0, this->parseNumber("0.5"));
213 }
214
215 ASSERT_NO_THROW(solver->solveEquations(this->env(), storm::OptimizationDirection::Maximize, x, b));
216 EXPECT_NEAR(x[0], this->parseNumber("0.99"), this->precision());
217 if (this->reportsBounds()) {
218 this->expectSolutionBoundsEnclose(*solver, 0, this->parseNumber("0.99"));
219 }
220}
221
222TEST(MinMaxLinearEquationSolverTest, TopologicalWithoutCyclesIsExact) {
223 // Two row groups whose only cycles are self loops, so the topological solver settles both by substitution.
224 storm::storage::SparseMatrixBuilder<double> builder(0, 0, 0, false, true);
225 builder.newRowGroup(0);
226 builder.addNextValue(0, 0, 0.5);
227 builder.addNextValue(0, 1, 0.25);
228 builder.newRowGroup(1);
229 builder.addNextValue(1, 1, 0.5);
230 storm::storage::SparseMatrix<double> A = builder.build(2, 2, 2);
231
233 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::Topological);
234 env.solver().topological().setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod::ValueIteration);
235
236 std::vector<double> x(2);
237 std::vector<double> b = {0.0, 0.5};
238
240 solver->setHasUniqueSolution(true);
241 solver->setHasNoEndComponents(true);
242 solver->setRequirementsChecked(true);
243 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
244
245 EXPECT_TRUE(solver->hasExactSolutionBounds()) << "An acyclic topological solve should report the values as exact.";
246 ASSERT_TRUE(solver->hasSolutionLowerBounds());
247 ASSERT_TRUE(solver->hasSolutionUpperBounds());
248 EXPECT_EQ(x, solver->getSolutionLowerBounds());
249 EXPECT_EQ(x, solver->getSolutionUpperBounds());
250}
251// Four states forming the two non-trivial SCCs {0, 1} and {2, 3}. The solution is 5/18, 2/9, 1/3 and 1/6.
252storm::storage::SparseMatrix<double> buildTwoSccMatrix() {
253 storm::storage::SparseMatrixBuilder<double> builder(0, 0, 0, false, true);
254 builder.newRowGroup(0);
255 builder.addNextValue(0, 1, 0.5);
256 builder.addNextValue(0, 2, 0.5);
257 builder.newRowGroup(1);
258 builder.addNextValue(1, 0, 0.5);
259 builder.addNextValue(1, 2, 0.25);
260 builder.newRowGroup(2);
261 builder.addNextValue(2, 3, 0.5);
262 builder.newRowGroup(3);
263 builder.addNextValue(3, 2, 0.5);
264 return builder.build(4, 4, 4);
265}
266
267std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<double>> createSolver(storm::Environment const& env, storm::storage::SparseMatrix<double> const& A) {
269 solver->setHasUniqueSolution(true);
270 solver->setHasNoEndComponents(true);
271 solver->setRequirementsChecked(true);
272 return solver;
273}
274
275TEST(MinMaxLinearEquationSolverTest, ValueIterationFromBelowReportsLowerBound) {
276 auto A = buildTwoSccMatrix();
277 std::vector<double> b = {0.0, 0.0, 0.25, 0.0};
278
280 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration);
282 env.solver().setForceSoundness(true);
283
284 std::vector<double> x(4);
285 auto solver = createSolver(env, A);
286 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
287
288 // Starting from zero, no sweep ever decreases a value, which places the iterate below the fixed point.
289 ASSERT_TRUE(solver->hasSolutionLowerBounds());
290 EXPECT_FALSE(solver->hasSolutionUpperBounds());
291 EXPECT_LE(solver->getSolutionLowerBounds()[0], 5.0 / 18.0);
292}
293
294TEST(MinMaxLinearEquationSolverTest, ValueIterationWithoutSoundnessReportsNoBounds) {
295 auto A = buildTwoSccMatrix();
296 std::vector<double> b = {0.0, 0.0, 0.25, 0.0};
297
299 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration);
301
302 std::vector<double> x(4);
303 auto solver = createSolver(env, A);
304 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
305
306 EXPECT_FALSE(solver->hasSolutionLowerBounds());
307 EXPECT_FALSE(solver->hasSolutionUpperBounds());
308}
309
310TEST(MinMaxLinearEquationSolverTest, InitialSchedulerDoesNotYieldBounds) {
311 storm::storage::SparseMatrixBuilder<double> builder(0, 0, 0, false, true);
312 builder.newRowGroup(0);
313 builder.addNextValue(0, 1, 0.5);
314 builder.addNextValue(1, 1, 0.25);
315 builder.newRowGroup(2);
316 builder.addNextValue(2, 1, 0.5);
317 storm::storage::SparseMatrix<double> A = builder.build(3, 2, 2);
318 std::vector<double> b = {0.0, 0.0, 0.25};
319
321 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration);
323 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
324 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Jacobi);
325
326 std::vector<double> x(2);
327 auto solver = createSolver(env, A);
328 solver->setInitialScheduler({1, 0});
329 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
330 EXPECT_NEAR(x[0], 0.25, 1e-6);
331
332 // The value of the initial scheduler bounds the solution, but only as accurately as it was computed itself.
333 EXPECT_FALSE(solver->hasSolutionLowerBounds());
334 EXPECT_FALSE(solver->hasSolutionUpperBounds());
335}
336
337TEST(MinMaxLinearEquationSolverTest, PolicyIterationWithInexactInnerSolveAddsNoBounds) {
338 auto A = buildTwoSccMatrix();
339 std::vector<double> b = {0.0, 0.0, 0.25, 0.0};
340
342 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration);
343 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
344 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::SoundValueIteration);
345
346 std::vector<double> x(4);
347 auto solver = createSolver(env, A);
348 solver->setBounds(0.0, 1.0);
349 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
350
351 // The inner solver encloses the values of the scheduler it was handed, but an inexact inner solve may have
352 // let policy iteration stop at a suboptimal one, which those bounds say nothing about. So the reported
353 // bounds are the ones that were known beforehand.
354 ASSERT_TRUE(solver->hasSolutionLowerBounds());
355 ASSERT_TRUE(solver->hasSolutionUpperBounds());
356 EXPECT_EQ(0.0, solver->getSolutionLowerBounds()[0]);
357 EXPECT_EQ(1.0, solver->getSolutionUpperBounds()[0]);
358}
359
360TEST(MinMaxLinearEquationSolverTest, OptimisticValueIterationStoppedEarlyStaysWithinItsBounds) {
361 auto A = buildTwoSccMatrix();
362 std::vector<double> b = {0.0, 0.0, 0.25, 0.0};
363
365 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::OptimisticValueIteration);
367
368 std::vector<double> x(4);
369 auto solver = createSolver(env, A);
370 solver->setBounds(0.0, 1.0);
371 EXPECT_FALSE(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
372
373 // The guess the iteration keeps above the solution is only verified on convergence, so a solve that the
374 // iteration limit stopped must hand back the vector it iterated from below rather than the middle of the two.
375 ASSERT_TRUE(solver->hasSolutionLowerBounds());
376 EXPECT_FALSE(solver->hasSolutionUpperBounds());
377 EXPECT_EQ(x, solver->getSolutionLowerBounds());
378 EXPECT_TRUE(solver->getSolutionBounds().encloses(x));
379}
380
381TEST(MinMaxLinearEquationSolverTest, TopologicalWithUnsoundSccMethodReportsNoBounds) {
382 auto A = buildTwoSccMatrix();
383 std::vector<double> b = {0.0, 0.0, 0.25, 0.0};
384
386 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::Topological);
387 env.solver().topological().setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod::ValueIteration);
389 env.solver().setForceSoundness(true);
390
391 std::vector<double> x(4);
392 auto solver = createSolver(env, A);
393 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
394
395 // The precision the SCCs were solved with is only an error bound if they certify it, which plain value
396 // iteration does not.
397 EXPECT_FALSE(solver->hasSolutionLowerBounds());
398 EXPECT_FALSE(solver->hasSolutionUpperBounds());
399}
400
401TEST(MinMaxLinearEquationSolverTest, TopologicalWithSoundSccMethodReportsBounds) {
402 auto A = buildTwoSccMatrix();
403 std::vector<double> b = {0.0, 0.0, 0.25, 0.0};
404
406 env.solver().minMax().setMethod(storm::solver::MinMaxMethod::Topological);
407 env.solver().topological().setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod::SoundValueIteration);
409 env.solver().setForceSoundness(true);
410
411 std::vector<double> x(4);
412 auto solver = createSolver(env, A);
413 solver->setBounds(0.0, 1.0);
414 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Maximize, x, b));
415
416 ASSERT_TRUE(solver->hasSolutionLowerBounds());
417 ASSERT_TRUE(solver->hasSolutionUpperBounds());
418 EXPECT_LE(solver->getSolutionLowerBounds()[0], 5.0 / 18.0);
419 EXPECT_LE(5.0 / 18.0, solver->getSolutionUpperBounds()[0]);
420}
421
422TEST(MinMaxLinearEquationSolverTest, SoundMethodsTerminateEarly) {
423 // State 0 has value 1 but converges slowly due to its self-loop, state 1 has value 0.5.
424 // The thresholds are already met after the first iteration, so every sound method should stop far from convergence.
425 storm::storage::SparseMatrixBuilder<double> builder(0, 0, 0, false, true);
426 builder.newRowGroup(0);
427 builder.addNextValue(0, 0, 0.99);
428 builder.newRowGroup(1);
429 builder.addNextValue(1, 1, 0.5);
430 storm::storage::SparseMatrix<double> A = builder.build(2, 2, 2);
431 std::vector<double> b = {0.01, 0.25};
432 storm::storage::BitVector filter(2, std::vector<uint64_t>{0});
433
434 for (auto method : {storm::solver::MinMaxMethod::SoundValueIteration, storm::solver::MinMaxMethod::IntervalIteration,
435 storm::solver::MinMaxMethod::GuessingValueIteration}) {
436 for (bool useLowerBound : {true, false}) {
437 SCOPED_TRACE(storm::solver::toString(method) + (useLowerBound ? " with lower bound" : " with upper bound"));
439 env.solver().minMax().setMethod(method);
440 env.solver().setForceSoundness(true);
442
444 solver->setHasUniqueSolution(true);
445 solver->setHasNoEndComponents(true);
446 solver->setBounds(0.0, 10.0);
447 if (useLowerBound) {
449 std::make_unique<storm::solver::TerminateIfFilteredExtremumExceedsThreshold<double>>(filter, false, 0.005, false));
450 } else {
451 solver->setTerminationCondition(std::make_unique<storm::solver::TerminateIfFilteredExtremumBelowThreshold<double>>(filter, false, 9.95, true));
452 }
453 std::vector<double> x(2);
454 ASSERT_NO_THROW(solver->solveEquations(env, storm::OptimizationDirection::Minimize, x, b));
455 // Without early termination, x[0] would be within the precision of 1.
456 EXPECT_GT(std::abs(x[0] - 1.0), 1e-3) << "x[0] = " << x[0];
457 }
458 }
459}
460
461TEST(IntervalIterationJustPreciseEnough, MinMax) {
462 storm::storage::SparseMatrixBuilder<double> builder(0, 0, 0, false, true);
463 builder.newRowGroup(0);
464 builder.addNextValue(0, 0, 0.9);
465 builder.addNextValue(1, 0, 0.9);
466 auto matrix = builder.build();
467 std::vector<double> b = {0.099, 0.05}; // Fixed points 0.99 and 0.5.
468 double const precision = 1e-3;
469
470 for (bool relative : {false, true}) {
471 for (auto dir : {storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Maximize}) {
472 SCOPED_TRACE(::testing::Message() << "relative=" << relative << ", maximize=" << storm::solver::maximize(dir));
473 auto env = DoubleIntervalIterationEnvironment::createEnvironment();
477 solver->setHasUniqueSolution(true);
478 solver->setHasNoEndComponents(true);
479 solver->setBounds(0.0, 1.0);
480 std::vector<double> x(1);
481 ASSERT_TRUE(solver->solveEquations(env, dir, x, b));
482 ASSERT_TRUE(solver->hasSolutionLowerBounds());
483 ASSERT_TRUE(solver->hasSolutionUpperBounds());
484 double const lower = solver->getSolutionLowerBounds()[0];
485 double const upper = solver->getSolutionUpperBounds()[0];
486 double const exact = storm::solver::maximize(dir) ? 0.99 : 0.5;
487 double const tolerance = precision * (relative ? lower : 1.0);
488 EXPECT_LE(lower, exact);
489 EXPECT_GE(upper, exact);
490 EXPECT_DOUBLE_EQ(x[0], (lower + upper) / 2.0);
491 EXPECT_NEAR(x[0], exact, precision * (relative ? exact : 1.0));
492 EXPECT_LE(upper - lower, 2.0 * tolerance);
493 // With this slow contraction, stopping at half this width takes unnecessary iterations.
494 EXPECT_GT(upper - lower, tolerance);
495 }
496 }
497}
498
499TEST(GuessingValueIterationPrecision, MinMaxSmallValues) {
500 // Regression for #1137: the requested tolerance must scale with small probabilities in relative mode.
501 storm::storage::SparseMatrixBuilder<double> builder(0, 0, 0, false, true);
502 builder.newRowGroup(0);
503 builder.addNextValue(0, 0, 0.9);
504 builder.newRowGroup(2);
505 auto matrix = builder.build(3, 2);
506
507 for (bool relative : {false, true}) {
508 for (double scale : {1.0, 1e-8}) {
509 for (auto direction : {storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Maximize}) {
510 SCOPED_TRACE(::testing::Message() << "relative=" << relative << ", scale=" << scale << ", direction=" << direction);
511 auto env = DoubleGuessingViEnvironment::createEnvironment();
516 solver->setHasUniqueSolution(true);
517 solver->setHasNoEndComponents(true);
518 solver->setBounds(0.0, 1.0);
519
520 std::vector<double> x(2);
521 std::vector<double> b = {1e-5 * scale, 5e-5 * scale, 0.0};
522 ASSERT_TRUE(solver->solveEquations(env, direction, x, b));
523 double expected = (storm::solver::minimize(direction) ? 5e-5 : 1e-4) * scale;
524 double tolerance = relative ? 1e-3 * expected : 1e-3;
525 EXPECT_NEAR(x[0], expected, tolerance);
526 EXPECT_EQ(x[1], 0.0);
527 }
528 }
529 }
530}
531} // namespace
TEST(RegionConstraintCheckerTest, AffineConstraintHoldsThroughout)
SolverEnvironment & solver()
void setMultiplicationStyle(storm::solver::MultiplicationStyle value)
storm::RationalNumber const & getPrecision() const
void setPrecision(storm::RationalNumber value)
void setMethod(storm::solver::MinMaxMethod value, bool isSetFromDefault=false)
void setMaximalNumberOfIterations(uint64_t value)
void setMethod(storm::solver::NativeLinearEquationSolverMethod value, bool isSetFromDefault=false)
TopologicalSolverEnvironment & topological()
void setLinearEquationSolverType(storm::solver::EquationSolverType const &value, bool isSetFromDefault=false)
MinMaxSolverEnvironment & minMax()
void setLinearEquationSolverPrecision(boost::optional< storm::RationalNumber > const &newPrecision, boost::optional< bool > const &relativePrecision=boost::none)
NativeSolverEnvironment & native()
void setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod value, bool isSetFromDefault=false)
void setTerminationCondition(std::unique_ptr< TerminationCondition< SolutionType > > terminationCondition)
Sets a custom termination condition that is used together with the regular termination condition of t...
void setBounds(SolutionType const &lower, SolutionType const &upper)
Sets bounds for the solution that can potentially be used by the solver.
std::vector< SolutionType > const & getSolutionUpperBounds() const
bool hasExactSolutionBounds() const
Retrieves whether the bounds computed by the last call to this solver coincide.
SolutionBounds< SolutionType > const & getSolutionBounds() const
Retrieves both bounds at once, either of which may be unset.
bool hasSolutionLowerBounds() const
Retrieves whether the last call to this solver computed a sound lower resp.
std::vector< SolutionType > const & getSolutionLowerBounds() const
Retrieves sound bounds on the solution that the last call to this solver computed.
virtual std::unique_ptr< MinMaxLinearEquationSolver< ValueType, SolutionType > > create(Environment const &env) const override
void setHasUniqueSolution(bool value=true)
Sets whether the solution to the min max equation system is known to be unique.
bool solveEquations(Environment const &env, OptimizationDirection d, std::vector< SolutionType > &x, std::vector< ValueType > const &b) const
Solves the equation system x = min/max(A*x + b) given by the parameters.
void setInitialScheduler(std::vector< uint_fast64_t > &&choices)
Sets a valid initial scheduler that is required by some solvers (see requirements of solvers).
void setRequirementsChecked(bool value=true)
Notifies the solver that the requirements for solving equations have been checked.
virtual MinMaxLinearEquationSolverRequirements getRequirements(Environment const &env, boost::optional< storm::solver::OptimizationDirection > const &direction=boost::none, bool const &hasInitialScheduler=false) const
Retrieves the requirements of this solver for solving equations with the current settings.
void setHasNoEndComponents(bool value=true)
Sets whether the min max equation system is known to not have any end components.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
A class that can be used to build a sparse matrix by adding value by value.
A class that holds a possibly non-square matrix in the compressed row storage format.
bool scale(int exp, storm::RationalNumber &r, storm::RationalNumber acc)
SFTBDDChecker::ValueType ValueType
NumberType parseNumber(std::string const &value)
Parse number from string.
bool constexpr maximize(OptimizationDirection d)
std::string toString(GurobiSolverMethod const &method)
Yields a string representation of the GurobiSolverMethod.
bool constexpr minimize(OptimizationDirection d)
storm::storage::BitVector filter(std::vector< T > const &values, std::function< bool(T const &value)> const &function)
Retrieves a bit vector containing all the indices for which the value at this position makes the give...
Definition vector.h:487
TargetType convertNumber(SourceType const &number)
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
Definition GraphTest.cpp:64
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes
Definition GraphTest.cpp:61