1#include "storm-config.h"
35std::string
const modelDescription = R
"(
40 [] s=0 -> 1/2 : (s'=1) + 1/2 : (s'=2);
57std::filesystem::path getTemporaryFilePath() {
59 auto tmpDir = std::filesystem::temp_directory_path(ec);
60 EXPECT_EQ(0, ec.value()) <<
"Unable to get temporary directory for check result export test: " << ec.message();
61 std::random_device rd;
62 std::filesystem::path result;
64 result = tmpDir / std::filesystem::path(
"storm_check_result_export_test_" + std::to_string(rd()) +
".json");
65 }
while (std::filesystem::exists(result));
74template<
typename ValueType>
78 ASSERT_EQ(1ull, formulas.size());
80 ASSERT_EQ(4ull, model->getNumberOfStates());
83 std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(env, *formulas[0]);
84 ASSERT_TRUE(result->isExplicitQuantitativeCheckResult());
85 auto const& values = result->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector();
86 ASSERT_EQ(4ull, values.size());
90 uint64_t numberOfInfiniteValues = 0;
91 for (
auto const& value : values) {
93 ++numberOfInfiniteValues;
96 ASSERT_EQ(2ull, numberOfInfiniteValues);
98 auto const path = getTemporaryFilePath();
100 std::ifstream exportedStream(path);
101 ASSERT_TRUE(exportedStream.good());
103 ASSERT_NO_THROW(exportedStream >> exported);
104 exportedStream.close();
105 std::filesystem::remove(path);
107 ASSERT_TRUE(exported.is_array());
108 ASSERT_EQ(values.size(), exported.size());
109 for (
auto const& entry : exported) {
110 ASSERT_TRUE(entry.count(
"s") == 1 && entry.count(
"v") == 1);
111 uint64_t
const state = entry.at(
"s").template get<uint64_t>();
112 ASSERT_LT(state, values.size());
115 ASSERT_TRUE(entry.at(
"v").is_string()) <<
"State " << state <<
" has an infinite value, but was exported as " << entry.at(
"v").dump() <<
".";
116 EXPECT_EQ(
"inf", entry.at(
"v").template get<std::string>());
118 ASSERT_TRUE(entry.at(
"v").is_number()) <<
"State " << state <<
" has the finite value " << values[state] <<
", but was exported as "
119 << entry.at(
"v").dump() <<
".";
130template<
typename ValueType>
138 ASSERT_NO_THROW(exported = result.
toJson());
139 ASSERT_TRUE(exported.is_array());
140 ASSERT_EQ(3ull, exported.size());
142 EXPECT_TRUE(exported[0].at(
"v").is_number());
144 ASSERT_TRUE(exported[1].at(
"v").is_string()) <<
"The negative infinity was exported as " << exported[1].at(
"v").dump() <<
".";
145 EXPECT_EQ(
"-inf", exported[1].at(
"v").
template get<std::string>());
146 ASSERT_TRUE(exported[2].at(
"v").is_string()) <<
"The positive infinity was exported as " << exported[2].at(
"v").dump() <<
".";
147 EXPECT_EQ(
"inf", exported[2].at(
"v").
template get<std::string>());
150TEST(ExportCheckResultTest, NegativeInfinityDouble) {
154TEST(ExportCheckResultTest, NegativeInfinityExact) {
163TEST(ExportCheckResultTest, PrintsTheApproximationOfAnExactValue) {
165 storm::RationalNumber
const third = storm::RationalNumber(1) / storm::RationalNumber(3);
168 std::stringstream out;
170 EXPECT_NE(std::string::npos, out.str().find(
"1/3")) <<
"The exact value is missing from " << out.str() <<
".";
171 EXPECT_NE(std::string::npos, out.str().find(
"(approx.")) <<
"The approximation is missing from " << out.str() <<
".";
177TEST(ExportCheckResultTest, PrintsNoApproximationOfAnInexactValue) {
180 std::stringstream out;
182 EXPECT_EQ(std::string::npos, out.str().find(
"(approx.")) <<
"An approximation was printed for " << out.str() <<
".";
188TEST(ExportCheckResultTest, RangeOutputShowsBounds) {
189 std::vector<double> values(10, 0.5);
190 values.front() = 0.25;
192 std::vector<double> lower(10, 0.4);
196 std::stringstream out;
198 EXPECT_EQ(
"[0.25, 0.5] (range). Solution bounds: [0.2, ?].", out.str());
204TEST(ExportCheckResultTest, ExactSolutionIsAnnouncedInsteadOfItsBounds) {
208 std::stringstream out;
209 result.writeToStream(out);
210 EXPECT_EQ(
"0.25. Exact solution.", out.str());
213TEST(ExportCheckResultTest, RangeOutputAnnouncesAnExactSolution) {
214 std::vector<double> values(10, 0.5);
215 values.front() = 0.25;
219 std::stringstream out;
221 EXPECT_EQ(
"[0.25, 0.5] (range). Exact solution.", out.str());
224TEST(ExportCheckResultTest, InfiniteRewardDouble) {
226 runExportTest<double>(env);
229TEST(ExportCheckResultTest, InfiniteRewardExact) {
233 runExportTest<storm::RationalNumber>(env);
TEST(ExportCheckResultTest, NegativeInfinityDouble)
void runNegativeInfinityExportTest()
No model checker hands out a negative infinity today, so this builds the check result directly.
void setMethod(storm::solver::EigenLinearEquationSolverMethod value, bool isSetFromDefault=false)
SolverEnvironment & solver()
void setLinearEquationSolverType(storm::solver::EquationSolverType const &value, bool isSetFromDefault=false)
EigenSolverEnvironment & eigen()
A quantitative check result over the states of a sparse model.
virtual std::ostream & writeToStream(std::ostream &out) const override
void setLowerBounds(vector_type lowerBounds)
Sets sound bounds on the actual values.
storm::json< ValueType > toJson(std::optional< storm::storage::sparse::Valuations > const &stateValuations=std::nullopt, std::optional< storm::models::sparse::StateLabeling > const &stateLabels=std::nullopt) const
void setValuesExact()
States that the values of this result are the exact ones, i.e.
static storm::prism::Program parseFromString(std::string const &input, std::string const &filename, bool prismCompatability=false)
Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM synt...
std::vector< storm::jani::Property > parsePropertiesForPrismProgram(std::string const &inputString, storm::prism::Program const &program, boost::optional< std::set< std::string > > const &propertyFilter)
std::shared_ptr< storm::models::sparse::Model< ValueType > > buildSparseModel(storm::storage::SymbolicModelDescription const &model, storm::builder::BuilderOptions const &options, typename storm::builder::ExplicitModelBuilder< ValueType >::Options const &explorationOptions=typename storm::builder::ExplicitModelBuilder< ValueType >::Options())
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
void exportCheckResultToJson(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::unique_ptr< storm::modelchecker::CheckResult > const &checkResult, std::string const &filename)
ExtendedValueType< ValueType > positiveInfinity()
std::vector< ExtendedValueType< ValueType > > widen(std::vector< ValueType > &&values)
Widens a vector of finite values into the extended value type.
ExtendedValueType< ValueType > negativeInfinity()
std::conditional_t< storm::NumberTraits< ValueType >::HasInfinity, ValueType, ExtendedNumber< ValueType > > ExtendedValueType
The type to use for values that may be infinite.
bool isInfinity(ValueType const &a)
ValueType const & getFinite(ExtendedNumber< ValueType > const &value)
TargetType convertNumber(SourceType const &number)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json