7#include "storm-config.h"
24class UmbRoundTripTest :
public ::testing::Test {
26 std::filesystem::path umbFile;
27 void removeUmbFile() {
28 if (!umbFile.empty() && std::filesystem::exists(umbFile)) {
30 std::filesystem::remove(umbFile);
31 ASSERT_EQ(ec.value(), 0) <<
"Unable to remove temporary file " << umbFile <<
" for UMB round trip test: " << ec.message();
35 void setUpUmbFileName() {
37 auto tmp = std::filesystem::temp_directory_path(ec);
38 ASSERT_EQ(ec.value(), 0) <<
"Unable to get temporary directory for UMB round trip test: " << ec.message();
39 std::random_device rd;
41 umbFile = tmp / std::filesystem::path(
"storm_umb_round_trip_test_" + std::to_string(rd()) +
".umb");
42 }
while (std::filesystem::exists(umbFile));
45 template<
typename ValueType>
46 void run(std::filesystem::path
const& prismfile, std::string
const& constants =
"", storm::umb::ExportOptions
const& exportOptions = {}) {
49 storm::umb::ImportOptions importOptions;
50 importOptions.
buildChoiceLabeling = exportOptions.allowChoiceLabelingAsActions || exportOptions.allowChoiceOriginsAsActions;
61 auto builder = storm::builder::ExplicitModelBuilder<ValueType>(program, generatorOptions);
62 auto model = builder.build();
64 auto assertEqualModel = [&model](
auto const& otherModelPtr) {
65 ASSERT_TRUE(otherModelPtr) <<
"No model.";
66 EXPECT_EQ(model->getType(), otherModelPtr->getType());
67 EXPECT_EQ(model->getNumberOfStates(), otherModelPtr->getNumberOfStates());
68 EXPECT_EQ(model->getNumberOfChoices(), otherModelPtr->getNumberOfChoices());
69 EXPECT_EQ(model->getNumberOfTransitions(), otherModelPtr->getNumberOfTransitions());
72 EXPECT_EQ(model->getTransitionMatrix(), otherModelPtr->getTransitionMatrix());
74 EXPECT_EQ(model->getStateLabeling(), otherModelPtr->getStateLabeling());
75 if (model->isNondeterministicModel() && model->hasChoiceLabeling()) {
77 EXPECT_EQ(model->getChoiceLabeling(), otherModelPtr->getChoiceLabeling());
79 EXPECT_EQ(model->getNumberOfRewardModels(), otherModelPtr->getNumberOfRewardModels());
80 for (
auto const& [name, rewardModel] : model->getRewardModels()) {
81 ASSERT_TRUE(otherModelPtr->hasRewardModel(name) || model->hasUniqueRewardModel()) <<
"Other model does not have reward model '" << name <<
"'.";
82 auto const& otherRewardModel = model->hasUniqueRewardModel() ? otherModelPtr->getUniqueRewardModel() : otherModelPtr->getRewardModel(name);
83 if (rewardModel.hasStateRewards()) {
84 ASSERT_TRUE(otherRewardModel.hasStateRewards());
85 EXPECT_EQ(rewardModel.getStateRewardVector(), otherRewardModel.getStateRewardVector());
87 if (rewardModel.hasStateActionRewards()) {
88 ASSERT_TRUE(otherRewardModel.hasStateActionRewards());
89 EXPECT_EQ(rewardModel.getStateActionRewardVector(), otherRewardModel.getStateActionRewardVector());
91 if (rewardModel.hasTransitionRewards()) {
92 ASSERT_TRUE(otherRewardModel.hasTransitionRewards());
93 EXPECT_EQ(rewardModel.getTransitionRewardMatrix(), otherRewardModel.getTransitionRewardMatrix());
100 umb1.encodeRationals();
101 std::stringstream validationErrors;
102 ASSERT_TRUE(umb1.validate(validationErrors)) << validationErrors.str();
103 validationErrors.clear();
105 assertEqualModel(model1);
110 ASSERT_TRUE(umb2.validate(validationErrors)) << validationErrors.str();
111 validationErrors.clear();
113 assertEqualModel(model2);
117 virtual void SetUp()
override {
119 GTEST_SKIP() <<
"Z3 not available.";
121#ifndef STORM_HAVE_LIBARCHIVE
122 GTEST_SKIP() <<
"LibArchive not available.";
126 virtual void TearDown()
override {
131TEST_F(UmbRoundTripTest, brp_dtmc) {
133 run<double>(STORM_TEST_RESOURCES_DIR
"/dtmc/brp-16-2.pm",
"", options);
134 run<storm::RationalNumber>(STORM_TEST_RESOURCES_DIR
"/dtmc/brp-16-2.pm",
"", options);
135 run<storm::Interval>(STORM_TEST_RESOURCES_DIR
"/dtmc/brp-16-2.pm",
"", options);
136 run<storm::RationalInterval>(STORM_TEST_RESOURCES_DIR
"/dtmc/brp-16-2.pm",
"", options);
138 run<double>(STORM_TEST_RESOURCES_DIR
"/dtmc/brp-16-2.pm",
"", options);
140 run<double>(STORM_TEST_RESOURCES_DIR
"/dtmc/brp-16-2.pm",
"", options);
142 run<double>(STORM_TEST_RESOURCES_DIR
"/dtmc/brp-16-2.pm",
"", options);
145TEST_F(UmbRoundTripTest, embedded_ctmc) {
147 run<double>(STORM_TEST_RESOURCES_DIR
"/ctmc/embedded2.sm",
"", options);
148 run<storm::RationalNumber>(STORM_TEST_RESOURCES_DIR
"/ma/polling.ma",
"N=3,Q=3", options);
149 run<storm::Interval>(STORM_TEST_RESOURCES_DIR
"/ma/polling.ma",
"N=3,Q=3", options);
150 run<storm::RationalInterval>(STORM_TEST_RESOURCES_DIR
"/ma/polling.ma",
"N=3,Q=3", options);
153TEST_F(UmbRoundTripTest, firewire_mdp) {
155 run<double>(STORM_TEST_RESOURCES_DIR
"/mdp/firewire3-0.5.nm",
"", options);
156 run<storm::RationalNumber>(STORM_TEST_RESOURCES_DIR
"/mdp/firewire3-0.5.nm",
"", options);
157 run<storm::Interval>(STORM_TEST_RESOURCES_DIR
"/mdp/firewire3-0.5.nm",
"", options);
158 run<storm::RationalInterval>(STORM_TEST_RESOURCES_DIR
"/mdp/firewire3-0.5.nm",
"", options);
161 run<double>(STORM_TEST_RESOURCES_DIR
"/mdp/firewire3-0.5.nm",
"", options);
164TEST_F(UmbRoundTripTest, polling_ma) {
166 run<double>(STORM_TEST_RESOURCES_DIR
"/ma/polling.ma",
"N=3,Q=3", options);
167 run<storm::RationalNumber>(STORM_TEST_RESOURCES_DIR
"/ma/polling.ma",
"N=3,Q=3", options);
168 run<storm::Interval>(STORM_TEST_RESOURCES_DIR
"/ma/polling.ma",
"N=3,Q=3", options);
169 run<storm::RationalInterval>(STORM_TEST_RESOURCES_DIR
"/ma/polling.ma",
"N=3,Q=3", options);
172TEST_F(UmbRoundTripTest, robot_imdp) {
174 run<storm::Interval>(STORM_TEST_RESOURCES_DIR
"/imdp/robot.prism",
"delta=0.5", options);
175 run<storm::RationalInterval>(STORM_TEST_RESOURCES_DIR
"/imdp/robot.prism",
"delta=0.5", options);
178TEST_F(UmbRoundTripTest, maze_pomdp) {
180 run<double>(STORM_TEST_RESOURCES_DIR
"/pomdp/maze2.prism",
"sl=0.5", options);
181 run<storm::RationalNumber>(STORM_TEST_RESOURCES_DIR
"/pomdp/maze2.prism",
"sl=0.5", options);
182 run<storm::Interval>(STORM_TEST_RESOURCES_DIR
"/pomdp/maze2.prism",
"sl=0.5", options);
183 run<storm::RationalInterval>(STORM_TEST_RESOURCES_DIR
"/pomdp/maze2.prism",
"sl=0.5", options);
188TEST(UmbTest, RationalEncoding) {
194 std::vector<storm::RationalNumber> values(17);
202 values[6] = int64max / uint64max;
203 values[7] = int64min / uint64max;
205 auto const simpleRationals = std::span<storm::RationalNumber>(values.data(), 8);
210 ASSERT_EQ(simpleRationals.size(), decoded1.size());
211 for (
size_t i = 0; i < simpleRationals.size(); ++i) {
212 EXPECT_EQ(simpleRationals[i], decoded1[i]) <<
" at index " << i;
216 values[8] = int64max + one;
217 values[9] = one / (uint64max + one);
218 values[10] = int64min - one;
219 values[11] = one / (int64min - one);
220 values[12] = (int64min - one) / (uint64max + one);
222 "949667607787274453086419753000949667607787274453086419753000949667607787274453086419753000949667607787274453086419753000949667607787274453086419753000"
223 "9496676077872744530864197530009496676077872744530864197530009496676077872744530864197530/"
224 "780116505469339517040847240228739241622101546262265311616467711470010820006007800398204693387501962318501358930877102188539546463329577703105788853954"
225 "134811616465520508472358467546262155762385699576193087775947700108638258539546825539241654967");
226 values[14] = one / values[13];
227 values[15] = -values[13];
228 values[16] = -values[14];
235 ASSERT_EQ(values.size(), decoded2.size());
236 for (
size_t i = 0; i < values.size(); ++i) {
237 EXPECT_EQ(values[i], decoded2[i]) <<
" at index " << i;
TEST_F(AssumptionCheckerTest, Brp_no_bisimulation)
TEST(UmbTest, RationalEncoding)
BuilderOptions & setBuildAllLabels(bool newValue=true)
Should all reward models be built?
BuilderOptions & setBuildChoiceLabels(bool newValue=true)
Should the choice labels be built?
BuilderOptions & setBuildAllRewardModels(bool newValue=true)
Should all reward models be built?
BuilderOptions & setBuildChoiceOrigins(bool newValue=true)
Should the origins the different choices be built?
static storm::prism::Program parse(std::string const &filename, bool prismCompatability=false)
Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax.
static uint64_t getMinimalRationalSize(InputRange &&input, bool multiplesOf64)
static std::vector< uint64_t > createUint64FromRationalRange(InputRange &&input, uint64_t const numberSize)
static auto uint64ToRationalRangeView(InputRange &&input, uint64_t const numberSize)
storm::builder::BuilderOptions NextStateGeneratorOptions
storm::umb::UmbModel importUmb(std::filesystem::path const &umbLocation, ImportOptions const &options)
void toArchive(storm::umb::UmbModel const &umbModel, std::filesystem::path const &archivePath, ExportOptions const &options)
std::shared_ptr< storm::models::sparse::Model< ValueType > > sparseModelFromUmb(storm::umb::UmbModel const &umbModel, ImportOptions const &options)
Constructs a sparse model from the given UMB model.
storm::umb::UmbModel sparseModelToUmb(storm::models::sparse::Model< ValueType > const &model, ExportOptions const &options)
storm::prism::Program preprocess(storm::prism::Program const &program, std::map< storm::expressions::Variable, storm::expressions::Expression > const &constantDefinitions)
TargetType convertNumber(SourceType const &number)
bool allowChoiceLabelingAsActions
Whether export of choice origins is enabled.
bool allowChoiceOriginsAsActions
Whether export of choice origins is enabled.
storm::io::CompressionMode compression
The type of compression used for the exported UMB model.
bool buildChoiceLabeling
Controls building of choice labelings.