1#include "storm-config.h"
16class NativeDoublePowerEnvironment {
18 typedef double ValueType;
19 static const bool isExact =
false;
20 static storm::Environment createEnvironment() {
21 storm::Environment env;
29class NativeDoublePowerRegMultEnvironment {
31 typedef double ValueType;
32 static const bool isExact =
false;
33 static storm::Environment createEnvironment() {
34 storm::Environment env;
43class NativeDoubleSoundValueIterationEnvironment {
45 typedef double ValueType;
46 static const bool isExact =
false;
47 static storm::Environment createEnvironment() {
48 storm::Environment env;
51 env.
solver().
native().
setMethod(storm::solver::NativeLinearEquationSolverMethod::SoundValueIteration);
58class NativeDoubleOptimisticValueIterationEnvironment {
60 typedef double ValueType;
61 static const bool isExact =
false;
62 static storm::Environment createEnvironment() {
63 storm::Environment env;
66 env.
solver().
native().
setMethod(storm::solver::NativeLinearEquationSolverMethod::OptimisticValueIteration);
73class NativeDoubleIntervalIterationEnvironment {
75 typedef double ValueType;
76 static const bool isExact =
false;
77 static storm::Environment createEnvironment() {
78 storm::Environment env;
88class NativeDoubleGuessingViEnvironment {
90 typedef double ValueType;
91 static const bool isExact =
false;
92 static storm::Environment createEnvironment() {
93 storm::Environment env;
96 env.
solver().
native().
setMethod(storm::solver::NativeLinearEquationSolverMethod::GuessingValueIteration);
103class NativeDoubleJacobiEnvironment {
105 typedef double ValueType;
106 static const bool isExact =
false;
107 static storm::Environment createEnvironment() {
108 storm::Environment env;
116class NativeDoubleGaussSeidelEnvironment {
118 typedef double ValueType;
119 static const bool isExact =
false;
120 static storm::Environment createEnvironment() {
121 storm::Environment env;
129class NativeDoubleSorEnvironment {
131 typedef double ValueType;
132 static const bool isExact =
false;
133 static storm::Environment createEnvironment() {
134 storm::Environment env;
142class NativeDoubleWalkerChaeEnvironment {
144 typedef double ValueType;
145 static const bool isExact =
false;
146 static storm::Environment createEnvironment() {
147 storm::Environment env;
156class NativeRationalRationalSearchEnvironment {
158 typedef storm::RationalNumber ValueType;
159 static const bool isExact =
true;
160 static storm::Environment createEnvironment() {
161 storm::Environment env;
168class EliminationRationalEnvironment {
170 typedef storm::RationalNumber ValueType;
171 static const bool isExact =
true;
172 static storm::Environment createEnvironment() {
173 storm::Environment env;
180class GmmGmresIluEnvironment {
183 static const bool isExact =
false;
184 static storm::Environment createEnvironment() {
185 storm::Environment env;
194class GmmGmresDiagonalEnvironment {
197 static const bool isExact =
false;
198 static storm::Environment createEnvironment() {
199 storm::Environment env;
208class GmmGmresNoneEnvironment {
211 static const bool isExact =
false;
212 static storm::Environment createEnvironment() {
213 storm::Environment env;
222class GmmBicgstabIluEnvironment {
225 static const bool isExact =
false;
226 static storm::Environment createEnvironment() {
227 storm::Environment env;
236class GmmQmrDiagonalEnvironment {
239 static const bool isExact =
false;
240 static storm::Environment createEnvironment() {
241 storm::Environment env;
251class EigenDGmresDiagonalEnvironment {
253 typedef double ValueType;
254 static const bool isExact =
false;
255 static storm::Environment createEnvironment() {
256 storm::Environment env;
265class EigenGmresIluEnvironment {
267 typedef double ValueType;
268 static const bool isExact =
false;
269 static storm::Environment createEnvironment() {
270 storm::Environment env;
279class EigenBicgstabNoneEnvironment {
281 typedef double ValueType;
282 static const bool isExact =
false;
283 static storm::Environment createEnvironment() {
284 storm::Environment env;
293class EigenDoubleLUEnvironment {
295 typedef double ValueType;
296 static const bool isExact =
false;
297 static storm::Environment createEnvironment() {
298 storm::Environment env;
305class EigenRationalLUEnvironment {
307 typedef storm::RationalNumber ValueType;
308 static const bool isExact =
true;
309 static storm::Environment createEnvironment() {
310 storm::Environment env;
317class TopologicalEigenRationalLUEnvironment {
319 typedef storm::RationalNumber ValueType;
320 static const bool isExact =
true;
321 static storm::Environment createEnvironment() {
322 storm::Environment env;
330template<
typename TestType>
331class LinearEquationSolverTest :
public ::testing::Test {
333 typedef typename TestType::ValueType ValueType;
334 LinearEquationSolverTest() : _environment(TestType::createEnvironment()) {}
335 storm::Environment
const& env()
const {
338 ValueType precision()
const {
341 ValueType
parseNumber(std::string
const& input)
const {
346 storm::Environment _environment;
349typedef ::testing::Types<NativeDoublePowerEnvironment, NativeDoublePowerRegMultEnvironment, NativeDoubleSoundValueIterationEnvironment,
350 NativeDoubleOptimisticValueIterationEnvironment, NativeDoubleGuessingViEnvironment, NativeDoubleIntervalIterationEnvironment,
351 NativeDoubleJacobiEnvironment, NativeDoubleGaussSeidelEnvironment, NativeDoubleSorEnvironment, NativeDoubleWalkerChaeEnvironment,
352 NativeRationalRationalSearchEnvironment, EliminationRationalEnvironment,
354 GmmGmresIluEnvironment, GmmGmresDiagonalEnvironment, GmmGmresNoneEnvironment, GmmBicgstabIluEnvironment, GmmQmrDiagonalEnvironment,
356 EigenDGmresDiagonalEnvironment, EigenGmresIluEnvironment, EigenBicgstabNoneEnvironment, EigenDoubleLUEnvironment,
357 EigenRationalLUEnvironment, TopologicalEigenRationalLUEnvironment>
362TYPED_TEST(LinearEquationSolverTest, solveEquationSystem) {
363 typedef typename TestFixture::ValueType
ValueType;
366 ASSERT_NO_THROW(builder.
addNextValue(0, 0, this->parseNumber(
"1/5")));
367 ASSERT_NO_THROW(builder.
addNextValue(0, 1, this->parseNumber(
"2/5")));
368 ASSERT_NO_THROW(builder.
addNextValue(0, 2, this->parseNumber(
"2/5")));
369 ASSERT_NO_THROW(builder.
addNextValue(1, 0, this->parseNumber(
"1/50")));
370 ASSERT_NO_THROW(builder.
addNextValue(1, 1, this->parseNumber(
"48/50")));
371 ASSERT_NO_THROW(builder.
addNextValue(1, 2, this->parseNumber(
"1/50")));
372 ASSERT_NO_THROW(builder.
addNextValue(2, 0, this->parseNumber(
"4/10")));
373 ASSERT_NO_THROW(builder.
addNextValue(2, 1, this->parseNumber(
"3/10")));
374 ASSERT_NO_THROW(builder.
addNextValue(2, 2, this->parseNumber(
"0")));
377 ASSERT_NO_THROW(A = builder.
build());
379 std::vector<ValueType> x(3);
387 auto requirements = factory.getRequirements(this->env());
388 requirements.clearUpperBounds();
389 requirements.clearLowerBounds();
390 ASSERT_FALSE(requirements.hasEnabledRequirement());
391 auto solver = factory.create(this->env(), A);
393 ASSERT_NO_THROW(solver->solveEquations(this->env(), x, b));
394 EXPECT_NEAR(x[0], this->
parseNumber(
"481/9"), this->precision());
395 EXPECT_NEAR(x[1], this->
parseNumber(
"457/9"), this->precision());
396 EXPECT_NEAR(x[2], this->
parseNumber(
"875/18"), this->precision());
399TEST(IntervalIterationJustPreciseEnough, Native) {
402 auto matrix = builder.
build();
403 std::vector<double> b = {0.099};
404 double const precision = 1e-3;
406 for (
bool relative : {
false,
true}) {
407 SCOPED_TRACE(::testing::Message() <<
"relative=" << relative);
408 auto env = NativeDoubleIntervalIterationEnvironment::createEnvironment();
412 solver->setBounds(0.0, 1.0);
413 std::vector<double> x(1);
414 ASSERT_TRUE(solver->solveEquations(env, x, b));
415 ASSERT_TRUE(solver->hasSolutionLowerBounds());
416 ASSERT_TRUE(solver->hasSolutionUpperBounds());
417 double const lower = solver->getSolutionLowerBounds()[0];
418 double const upper = solver->getSolutionUpperBounds()[0];
419 double const tolerance = precision * (relative ? lower : 1.0);
420 EXPECT_LE(lower, 0.99);
421 EXPECT_GE(upper, 0.99);
422 EXPECT_DOUBLE_EQ(x[0], (lower + upper) / 2.0);
423 EXPECT_NEAR(x[0], 0.99, precision * (relative ? 0.99 : 1.0));
424 EXPECT_LE(upper - lower, 2.0 * tolerance);
426 EXPECT_GT(upper - lower, tolerance);
430TEST(GuessingValueIterationPrecision, NativeSmallValues) {
435 auto matrix = builder.
build();
437 for (
bool relative : {
false,
true}) {
438 for (
double scale : {1.0, 1e-8}) {
439 SCOPED_TRACE(::testing::Message() <<
"relative=" << relative <<
", scale=" << scale);
440 auto env = NativeDoubleGuessingViEnvironment::createEnvironment();
445 solver->setBounds(-1.0, 1.0);
447 std::vector<double> x(3);
448 std::vector<double> b = {1e-5 *
scale, -1e-5 *
scale, 0.0};
449 ASSERT_TRUE(solver->solveEquations(env, x, b));
450 double expected = 1e-4 *
scale;
451 double tolerance = relative ? 1e-3 * expected : 1e-3;
452 EXPECT_NEAR(x[0], expected, tolerance);
453 EXPECT_NEAR(x[1], -expected, tolerance);
454 EXPECT_EQ(x[2], 0.0);
459template<
typename ValueType>
460void testEliminationWithAbsorbingStates(std::vector<std::vector<std::pair<uint64_t, ValueType>>>
const& rows, std::vector<ValueType>
const& b,
461 std::vector<ValueType>
const& expected) {
463 for (uint64_t row = 0; row < rows.size(); ++row) {
464 for (
auto const& entry : rows[row]) {
468 auto matrix = builder.
build();
473 std::vector<ValueType> x(b.size());
474 ASSERT_NO_THROW(solver.solveEquations(env, x, b));
475 ASSERT_EQ(expected.size(), x.size());
476 for (uint64_t i = 0;
i < x.size(); ++
i) {
477 EXPECT_EQ(expected[i], x[i]);
481TEST(EliminationLinearEquationSolver, AbsorbingState) {
488TEST(EliminationLinearEquationSolver, AbsorbingTwoCycle) {
493 testEliminationWithAbsorbingStates<storm::RationalNumber>({{{1,
one}}, {{0,
one}}}, {
zero,
zero}, {
zero,
zero});
496 testEliminationWithAbsorbingStates<double>({{{1, 1.0}}, {{0, 1.0}}}, {0.0, 0.0}, {0.0, 0.0});
499TEST(EliminationLinearEquationSolver, AbsorbingSinkReachability) {
504 testEliminationWithAbsorbingStates<storm::RationalNumber>({{{1, half}}, {{2,
one}}, {{1,
one}}}, {half,
zero,
zero}, {half,
zero,
zero});
507TEST(NativeLinearEquationSolver, SoundMethodsTerminateEarly) {
514 std::vector<double> b = {0.01, 0.25};
518 {storm::solver::NativeLinearEquationSolverMethod::SoundValueIteration, storm::solver::NativeLinearEquationSolverMethod::IntervalIteration,
519 storm::solver::NativeLinearEquationSolverMethod::GuessingValueIteration}) {
520 for (
bool useLowerBound : {
true,
false}) {
531 auto solver = factory.create(env, A);
532 solver->setBounds(0.0, 10.0);
534 solver->setTerminationCondition(
539 std::vector<double> x(2);
540 ASSERT_NO_THROW(solver->solveEquations(env, x, b));
542 EXPECT_GT(std::abs(x[0] - 1.0), 1e-3) <<
"x[0] = " << x[0];
TEST(RegionConstraintCheckerTest, AffineConstraintHoldsThroughout)
void setPrecision(storm::RationalNumber value)
void setMethod(storm::solver::EigenLinearEquationSolverMethod value, bool isSetFromDefault=false)
void setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner value)
SolverEnvironment & solver()
void setMethod(storm::solver::GmmxxLinearEquationSolverMethod value)
void setPrecision(storm::RationalNumber value)
void setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner value)
void setPowerMethodMultiplicationStyle(storm::solver::MultiplicationStyle value)
void setMaximalNumberOfIterations(uint64_t value)
void setRelativeTerminationCriterion(bool value)
void setPrecision(storm::RationalNumber value)
void setMethod(storm::solver::NativeLinearEquationSolverMethod value, bool isSetFromDefault=false)
TopologicalSolverEnvironment & topological()
void setLinearEquationSolverType(storm::solver::EquationSolverType const &value, bool isSetFromDefault=false)
EigenSolverEnvironment & eigen()
void setForceSoundness(bool value)
NativeSolverEnvironment & native()
GmmxxSolverEnvironment & gmmxx()
void setUnderlyingEquationSolverType(storm::solver::EquationSolverType value, bool isSetFromDefault=false)
A class that uses gaussian elimination to implement the LinearEquationSolver interface.
virtual std::unique_ptr< LinearEquationSolver< ValueType > > create(Environment const &env) const override
Creates an equation solver with the current settings, but without a matrix.
A bit vector that is internally represented as a vector of 64-bit values.
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
A class that holds a possibly non-square matrix in the compressed row storage format.
void convertToEquationSystem()
Transforms the matrix into an equation system.
bool scale(int exp, storm::RationalNumber &r, storm::RationalNumber acc)
SFTBDDChecker::ValueType ValueType
NumberType parseNumber(std::string const &value)
Parse number from string.
std::string toString(GurobiSolverMethod const &method)
Yields a string representation of the GurobiSolverMethod.
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...
TargetType convertNumber(SourceType const &number)
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes