Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
LinearEquationSolverTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
13
14namespace {
15
16class NativeDoublePowerEnvironment {
17 public:
18 typedef double ValueType;
19 static const bool isExact = false;
20 static storm::Environment createEnvironment() {
21 storm::Environment env;
22 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
23 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power);
25 return env;
26 }
27};
28
29class NativeDoublePowerRegMultEnvironment {
30 public:
31 typedef double ValueType;
32 static const bool isExact = false;
33 static storm::Environment createEnvironment() {
34 storm::Environment env;
35 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
36 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power);
39 return env;
40 }
41};
42
43class NativeDoubleSoundValueIterationEnvironment {
44 public:
45 typedef double ValueType;
46 static const bool isExact = false;
47 static storm::Environment createEnvironment() {
48 storm::Environment env;
49 env.solver().setForceSoundness(true);
50 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
51 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::SoundValueIteration);
54 return env;
55 }
56};
57
58class NativeDoubleOptimisticValueIterationEnvironment {
59 public:
60 typedef double ValueType;
61 static const bool isExact = false;
62 static storm::Environment createEnvironment() {
63 storm::Environment env;
64 env.solver().setForceSoundness(true);
65 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
66 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::OptimisticValueIteration);
69 return env;
70 }
71};
72
73class NativeDoubleIntervalIterationEnvironment {
74 public:
75 typedef double ValueType;
76 static const bool isExact = false;
77 static storm::Environment createEnvironment() {
78 storm::Environment env;
79 env.solver().setForceSoundness(true);
80 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
81 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::IntervalIteration);
84 return env;
85 }
86};
87
88class NativeDoubleGuessingViEnvironment {
89 public:
90 typedef double ValueType;
91 static const bool isExact = false;
92 static storm::Environment createEnvironment() {
93 storm::Environment env;
94 env.solver().setForceSoundness(true);
95 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
96 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::GuessingValueIteration);
99 return env;
100 }
101};
102
103class NativeDoubleJacobiEnvironment {
104 public:
105 typedef double ValueType;
106 static const bool isExact = false;
107 static storm::Environment createEnvironment() {
108 storm::Environment env;
109 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
110 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Jacobi);
112 return env;
113 }
114};
115
116class NativeDoubleGaussSeidelEnvironment {
117 public:
118 typedef double ValueType;
119 static const bool isExact = false;
120 static storm::Environment createEnvironment() {
121 storm::Environment env;
122 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
123 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::GaussSeidel);
125 return env;
126 }
127};
128
129class NativeDoubleSorEnvironment {
130 public:
131 typedef double ValueType;
132 static const bool isExact = false;
133 static storm::Environment createEnvironment() {
134 storm::Environment env;
135 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
136 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::SOR);
138 return env;
139 }
140};
141
142class NativeDoubleWalkerChaeEnvironment {
143 public:
144 typedef double ValueType;
145 static const bool isExact = false;
146 static storm::Environment createEnvironment() {
147 storm::Environment env;
148 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
149 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::WalkerChae);
152 return env;
153 }
154};
155
156class NativeRationalRationalSearchEnvironment {
157 public:
158 typedef storm::RationalNumber ValueType;
159 static const bool isExact = true;
160 static storm::Environment createEnvironment() {
161 storm::Environment env;
162 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
163 env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::RationalSearch);
164 return env;
165 }
166};
167
168class EliminationRationalEnvironment {
169 public:
170 typedef storm::RationalNumber ValueType;
171 static const bool isExact = true;
172 static storm::Environment createEnvironment() {
173 storm::Environment env;
174 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Elimination);
175 return env;
176 }
177};
178
179#ifdef STORM_HAVE_GMM
180class GmmGmresIluEnvironment {
181 public:
182 typedef double ValueType;
183 static const bool isExact = false;
184 static storm::Environment createEnvironment() {
185 storm::Environment env;
186 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx);
187 env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres);
188 env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu);
190 return env;
191 }
192};
193
194class GmmGmresDiagonalEnvironment {
195 public:
196 typedef double ValueType;
197 static const bool isExact = false;
198 static storm::Environment createEnvironment() {
199 storm::Environment env;
200 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx);
201 env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres);
202 env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Diagonal);
204 return env;
205 }
206};
207
208class GmmGmresNoneEnvironment {
209 public:
210 typedef double ValueType;
211 static const bool isExact = false;
212 static storm::Environment createEnvironment() {
213 storm::Environment env;
214 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx);
215 env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres);
216 env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::None);
218 return env;
219 }
220};
221
222class GmmBicgstabIluEnvironment {
223 public:
224 typedef double ValueType;
225 static const bool isExact = false;
226 static storm::Environment createEnvironment() {
227 storm::Environment env;
228 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx);
229 env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Bicgstab);
230 env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu);
232 return env;
233 }
234};
235
236class GmmQmrDiagonalEnvironment {
237 public:
238 typedef double ValueType;
239 static const bool isExact = false;
240 static storm::Environment createEnvironment() {
241 storm::Environment env;
242 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx);
243 env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Qmr);
244 env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Diagonal);
246 return env;
247 }
248};
249#endif
250
251class EigenDGmresDiagonalEnvironment {
252 public:
253 typedef double ValueType;
254 static const bool isExact = false;
255 static storm::Environment createEnvironment() {
256 storm::Environment env;
257 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen);
258 env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::DGmres);
259 env.solver().eigen().setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner::Diagonal);
261 return env;
262 }
263};
264
265class EigenGmresIluEnvironment {
266 public:
267 typedef double ValueType;
268 static const bool isExact = false;
269 static storm::Environment createEnvironment() {
270 storm::Environment env;
271 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen);
272 env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::Gmres);
273 env.solver().eigen().setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner::Ilu);
275 return env;
276 }
277};
278
279class EigenBicgstabNoneEnvironment {
280 public:
281 typedef double ValueType;
282 static const bool isExact = false;
283 static storm::Environment createEnvironment() {
284 storm::Environment env;
285 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen);
286 env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::Bicgstab);
287 env.solver().eigen().setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner::None);
289 return env;
290 }
291};
292
293class EigenDoubleLUEnvironment {
294 public:
295 typedef double ValueType;
296 static const bool isExact = false;
297 static storm::Environment createEnvironment() {
298 storm::Environment env;
299 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen);
300 env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU);
301 return env;
302 }
303};
304
305class EigenRationalLUEnvironment {
306 public:
307 typedef storm::RationalNumber ValueType;
308 static const bool isExact = true;
309 static storm::Environment createEnvironment() {
310 storm::Environment env;
311 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen);
312 env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU);
313 return env;
314 }
315};
316
317class TopologicalEigenRationalLUEnvironment {
318 public:
319 typedef storm::RationalNumber ValueType;
320 static const bool isExact = true;
321 static storm::Environment createEnvironment() {
322 storm::Environment env;
323 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Topological);
324 env.solver().topological().setUnderlyingEquationSolverType(storm::solver::EquationSolverType::Eigen);
325 env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU);
326 return env;
327 }
328};
329
330template<typename TestType>
331class LinearEquationSolverTest : public ::testing::Test {
332 public:
333 typedef typename TestType::ValueType ValueType;
334 LinearEquationSolverTest() : _environment(TestType::createEnvironment()) {}
335 storm::Environment const& env() const {
336 return _environment;
337 }
338 ValueType precision() const {
339 return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");
340 }
341 ValueType parseNumber(std::string const& input) const {
343 }
344
345 private:
346 storm::Environment _environment;
347};
348
349typedef ::testing::Types<NativeDoublePowerEnvironment, NativeDoublePowerRegMultEnvironment, NativeDoubleSoundValueIterationEnvironment,
350 NativeDoubleOptimisticValueIterationEnvironment, NativeDoubleGuessingViEnvironment, NativeDoubleIntervalIterationEnvironment,
351 NativeDoubleJacobiEnvironment, NativeDoubleGaussSeidelEnvironment, NativeDoubleSorEnvironment, NativeDoubleWalkerChaeEnvironment,
352 NativeRationalRationalSearchEnvironment, EliminationRationalEnvironment,
353#ifdef STORM_HAVE_GMM
354 GmmGmresIluEnvironment, GmmGmresDiagonalEnvironment, GmmGmresNoneEnvironment, GmmBicgstabIluEnvironment, GmmQmrDiagonalEnvironment,
355#endif
356 EigenDGmresDiagonalEnvironment, EigenGmresIluEnvironment, EigenBicgstabNoneEnvironment, EigenDoubleLUEnvironment,
357 EigenRationalLUEnvironment, TopologicalEigenRationalLUEnvironment>
359
360TYPED_TEST_SUITE(LinearEquationSolverTest, TestingTypes, );
361
362TYPED_TEST(LinearEquationSolverTest, solveEquationSystem) {
363 typedef typename TestFixture::ValueType ValueType;
364 ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<ValueType> builder);
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")));
375
377 ASSERT_NO_THROW(A = builder.build());
378
379 std::vector<ValueType> x(3);
380 std::vector<ValueType> b = {this->parseNumber("3"), this->parseNumber("-0.01"), this->parseNumber("12")};
381
383 if (factory.getEquationProblemFormat(this->env()) == storm::solver::LinearEquationSolverProblemFormat::EquationSystem) {
385 }
386
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);
392 solver->setBounds(this->parseNumber("-100"), this->parseNumber("100"));
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());
397}
398
399TEST(IntervalIterationJustPreciseEnough, Native) {
401 builder.addNextValue(0, 0, 0.9);
402 auto matrix = builder.build();
403 std::vector<double> b = {0.099}; // Fixed point 0.99.
404 double const precision = 1e-3;
405
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);
425 // With this slow contraction, stopping at half this width takes unnecessary iterations.
426 EXPECT_GT(upper - lower, tolerance);
427 }
428}
429
430TEST(GuessingValueIterationPrecision, NativeSmallValues) {
431 // Also cover negative solutions and an exact zero when checking relative convergence.
433 builder.addNextValue(0, 0, 0.9);
434 builder.addNextValue(1, 1, 0.9);
435 auto matrix = builder.build();
436
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);
446
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);
455 }
456 }
457}
458
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) {
462 storm::storage::SparseMatrixBuilder<ValueType> builder(rows.size(), rows.size(), 0);
463 for (uint64_t row = 0; row < rows.size(); ++row) {
464 for (auto const& entry : rows[row]) {
465 builder.addNextValue(row, entry.first, entry.second);
466 }
467 }
468 auto matrix = builder.build();
469
471 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Elimination);
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]);
478 }
479}
480
481TEST(EliminationLinearEquationSolver, AbsorbingState) {
482 // Regression test for issue #86: the elimination-based solver must handle a single absorbing state
483 // (a one on the diagonal), for which the least fixed point is zero.
485 testEliminationWithAbsorbingStates<storm::RationalNumber>({{{0, storm::utility::one<storm::RationalNumber>()}}}, {zero}, {zero});
486}
487
488TEST(EliminationLinearEquationSolver, AbsorbingTwoCycle) {
489 // Regression test for issue #86: when eliminating one state of a probability-1 cycle, the remaining state
490 // obtains a one on the diagonal (i.e., it becomes absorbing) and must be handled by the eliminator.
493 testEliminationWithAbsorbingStates<storm::RationalNumber>({{{1, one}}, {{0, one}}}, {zero, zero}, {zero, zero});
494
495 // Also check the double instantiation.
496 testEliminationWithAbsorbingStates<double>({{{1, 1.0}}, {{0, 1.0}}}, {0.0, 0.0}, {0.0, 0.0});
497}
498
499TEST(EliminationLinearEquationSolver, AbsorbingSinkReachability) {
500 // A transient state can either reach the target with probability one half or fall into an absorbing sink.
504 testEliminationWithAbsorbingStates<storm::RationalNumber>({{{1, half}}, {{2, one}}, {{1, one}}}, {half, zero, zero}, {half, zero, zero});
505}
506
507TEST(NativeLinearEquationSolver, SoundMethodsTerminateEarly) {
508 // State 0 has value 1 but converges slowly due to its self-loop, state 1 has value 0.5.
509 // The thresholds are already met after the first iteration, so every sound method should stop far from convergence.
511 builder.addNextValue(0, 0, 0.99);
512 builder.addNextValue(1, 1, 0.5);
514 std::vector<double> b = {0.01, 0.25};
515 storm::storage::BitVector filter(2, std::vector<uint64_t>{0});
516
517 for (auto method :
518 {storm::solver::NativeLinearEquationSolverMethod::SoundValueIteration, storm::solver::NativeLinearEquationSolverMethod::IntervalIteration,
519 storm::solver::NativeLinearEquationSolverMethod::GuessingValueIteration}) {
520 for (bool useLowerBound : {true, false}) {
521 SCOPED_TRACE(storm::solver::toString(method) + (useLowerBound ? " with lower bound" : " with upper bound"));
523 env.solver().setForceSoundness(true);
524 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native);
525 env.solver().native().setMethod(method);
528
530 ASSERT_EQ(factory.getEquationProblemFormat(env), storm::solver::LinearEquationSolverProblemFormat::FixedPointSystem);
531 auto solver = factory.create(env, A);
532 solver->setBounds(0.0, 10.0);
533 if (useLowerBound) {
534 solver->setTerminationCondition(
535 std::make_unique<storm::solver::TerminateIfFilteredExtremumExceedsThreshold<double>>(filter, false, 0.005, false));
536 } else {
537 solver->setTerminationCondition(std::make_unique<storm::solver::TerminateIfFilteredExtremumBelowThreshold<double>>(filter, false, 9.95, true));
538 }
539 std::vector<double> x(2);
540 ASSERT_NO_THROW(solver->solveEquations(env, x, b));
541 // Without early termination, x[0] would be within the precision of 1.
542 EXPECT_GT(std::abs(x[0] - 1.0), 1e-3) << "x[0] = " << x[0];
543 }
544 }
545}
546} // namespace
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 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()
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.
Definition BitVector.h:16
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...
Definition vector.h:487
ValueType zero()
Definition constants.cpp:26
ValueType one()
Definition constants.cpp:21
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