Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
MemoryStructureTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
9
10namespace {
11std::shared_ptr<storm::models::sparse::Mdp<double>> buildTinyMdp() {
12 // 3-state chain: 0 -> 1 -> 2 (self-loop)
13 // State 0 is initial, state 2 is a "goal" state.
14 uint64_t numStates = 3;
15 storm::storage::SparseMatrixBuilder<double> builder(numStates, numStates, numStates, true, true, numStates);
16 builder.newRowGroup(0);
17 builder.addNextValue(0, 1, 1.0);
18 builder.newRowGroup(1);
19 builder.addNextValue(1, 2, 1.0);
20 builder.newRowGroup(2);
21 builder.addNextValue(2, 2, 1.0);
22 auto matrix = builder.build();
23
24 storm::models::sparse::StateLabeling labeling(numStates);
25 labeling.addLabel("init");
26 labeling.addLabel("goal");
27 labeling.addLabelToState("init", 0);
28 labeling.addLabelToState("goal", 2);
29
30 return std::make_shared<storm::models::sparse::Mdp<double>>(std::move(matrix), std::move(labeling));
31}
32
35 storm::storage::BitVector goalStates(mdp.getNumberOfStates(), false);
36 goalStates.set(2, true);
37 storm::storage::BitVector allStates(mdp.getNumberOfStates(), true);
38 builder.setTransition(0, 0, ~goalStates);
39 builder.setTransition(0, 1, goalStates);
40 builder.setTransition(1, 1, allStates);
41 return builder.build();
42}
43} // namespace
44
45TEST(MemoryStructure, OnlyInitialStatesRelevantDefault) {
46 auto mdp = buildTinyMdp();
48 storm::storage::BitVector allStates(3, true);
49 builder.setTransition(0, 0, allStates);
50 auto mem = builder.build();
51
52 EXPECT_TRUE(mem.isOnlyInitialStatesRelevantSet());
53 EXPECT_EQ(1u, mem.getInitialMemoryStates().size());
54}
55
56TEST(MemoryStructure, OnlyInitialStatesRelevantFalse) {
57 auto mdp = buildTinyMdp();
59 storm::storage::BitVector allStates(3, true);
60 builder.setTransition(0, 0, allStates);
61 builder.setTransition(1, 1, allStates);
62 auto mem = builder.build();
63
64 EXPECT_FALSE(mem.isOnlyInitialStatesRelevantSet());
65 EXPECT_EQ(3u, mem.getInitialMemoryStates().size());
66}
67
68TEST(MemoryStructure, ProductPropagatesOnlyInitialStatesRelevant) {
69 auto mdp = buildTinyMdp();
70 auto mem1 = buildGoalMemoryStructure(*mdp);
71 auto mem2 = buildGoalMemoryStructure(*mdp);
72
73 EXPECT_FALSE(mem1.isOnlyInitialStatesRelevantSet());
74 EXPECT_FALSE(mem2.isOnlyInitialStatesRelevantSet());
75
76 auto prod = mem1.product(mem2);
77 EXPECT_FALSE(prod.isOnlyInitialStatesRelevantSet()) << "product of two non-initial-only structures should remain non-initial-only";
78 EXPECT_EQ(3u, prod.getInitialMemoryStates().size());
79}
80
81TEST(MemoryStructure, ProductOfTrivialMemoryStructuresIsTrivial) {
82 auto mdp = buildTinyMdp();
85
86 EXPECT_TRUE(mem1.isOnlyInitialStatesRelevantSet());
87 EXPECT_TRUE(mem2.isOnlyInitialStatesRelevantSet());
88
89 auto prod = mem1.product(mem2);
90 EXPECT_TRUE(prod.isOnlyInitialStatesRelevantSet()) << "product of two initial-only structures should remain initial-only";
91 EXPECT_EQ(1u, prod.getInitialMemoryStates().size());
92}
93
94TEST(MemoryStructure, ProductModelWithOnlyInitialStatesRelevantFalse) {
95 auto mdp = buildTinyMdp();
96 auto mem1 = buildGoalMemoryStructure(*mdp);
97 auto mem2 = buildGoalMemoryStructure(*mdp);
98 auto prodMem = mem1.product(mem2);
99
100 ASSERT_FALSE(prodMem.isOnlyInitialStatesRelevantSet());
101
102 // This must not fire the STORM_LOG_ASSERT in SparseModelMemoryProduct::initialize().
103 auto productType = prodMem.product(*mdp);
104 auto productModel = productType.build();
105
106 EXPECT_EQ(4u, productModel->getNumberOfStates());
107 EXPECT_EQ(3u, productModel->getInitialStates().getNumberOfSetBits());
108}
109
110TEST(MemoryStructure, ProductModelWithOnlyInitialStatesRelevantTrue) {
111 auto mdp = buildTinyMdp();
113 storm::storage::BitVector goalStates(3, false);
114 goalStates.set(2, true);
115 storm::storage::BitVector allStates(3, true);
116 builder.setTransition(0, 0, ~goalStates);
117 builder.setTransition(0, 1, goalStates);
118 builder.setTransition(1, 1, allStates);
119 builder.setInitialMemoryState(0, 0); // only initial model state (0) gets a memory state
120 auto mem = builder.build();
121
122 ASSERT_TRUE(mem.isOnlyInitialStatesRelevantSet());
123 EXPECT_EQ(1u, mem.getInitialMemoryStates().size());
124
125 auto productType = mem.product(*mdp);
126 auto productModel = productType.build();
127
128 // Only 1 initial product state (one initial model state * one initial memory state).
129 EXPECT_EQ(1u, productModel->getInitialStates().getNumberOfSetBits());
130}
131
132TEST(MemoryStructure, StateLabelingRespectsOnlyInitialStatesRelevantFalse) {
133 auto mdp = buildTinyMdp();
134 auto mem = buildGoalMemoryStructure(*mdp);
135 ASSERT_FALSE(mem.isOnlyInitialStatesRelevantSet());
136
137 auto productType = mem.product(*mdp);
138 auto productModel = productType.build();
139
140 // The "init" label should mark exactly one product state per model state.
141 auto const& initLabeling = productModel->getStateLabeling();
142 std::set<std::string> labels = initLabeling.getLabels();
143 ASSERT_NE(labels.end(), labels.find("init"));
144
145 storm::storage::BitVector initStates = initLabeling.getStates("init");
146 EXPECT_EQ(3u, initStates.getNumberOfSetBits());
147}
TEST(MemoryStructure, OnlyInitialStatesRelevantDefault)
This class represents a (discrete-time) Markov decision process.
Definition Mdp.h:13
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:163
This class manages the labeling of the state space with a number of (atomic) labels.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
void setInitialMemoryState(uint_fast64_t initialModelState, uint_fast64_t initialMemoryState)
Specifies for the given state of the model the corresponding initial memory state.
MemoryStructure build()
Builds the memory structure.
static MemoryStructure buildTrivialMemoryStructure(storm::models::sparse::Model< ValueType, RewardModelType > const &model)
Builds a trivial memory structure for the given model (consisting of a single memory state).
void setTransition(uint_fast64_t const &startState, uint_fast64_t const &goalState, storm::storage::BitVector const &modelStates, boost::optional< storm::storage::BitVector > const &modelChoices=boost::none)
Specifies a transition of the memory structure.
This class represents a (deterministic) memory structure that can be used to encode certain events (s...
A class that can be used to build a sparse matrix by adding value by value.