Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
Partition.cpp
Go to the documentation of this file.
2
4
6
11
14
17
20
24
26
27namespace storm {
28namespace dd {
29namespace bisimulation {
30
31template<storm::dd::DdType DdType, typename ValueType>
32Partition<DdType, ValueType>::Partition() : nextFreeBlockIndex(0) {
33 // Intentionally left empty.
34}
35
36template<storm::dd::DdType DdType, typename ValueType>
38 std::pair<storm::expressions::Variable, storm::expressions::Variable> const& blockVariables, uint64_t numberOfBlocks,
39 uint64_t nextFreeBlockIndex, boost::optional<storm::dd::Add<DdType, ValueType>> const& changedStates)
40 : partition(partitionAdd),
41 changedStates(changedStates),
42 blockVariables(blockVariables),
43 numberOfBlocks(numberOfBlocks),
44 nextFreeBlockIndex(nextFreeBlockIndex) {
45 // Intentionally left empty.
46}
47
48template<storm::dd::DdType DdType, typename ValueType>
50 std::pair<storm::expressions::Variable, storm::expressions::Variable> const& blockVariables, uint64_t numberOfBlocks,
51 uint64_t nextFreeBlockIndex, boost::optional<storm::dd::Bdd<DdType>> const& changedStates)
52 : partition(partitionBdd),
53 changedStates(changedStates),
54 blockVariables(blockVariables),
55 numberOfBlocks(numberOfBlocks),
56 nextFreeBlockIndex(nextFreeBlockIndex) {
57 // Intentionally left empty.
58}
59
60template<storm::dd::DdType DdType, typename ValueType>
62 return this->partition == other.partition && this->blockVariables == other.blockVariables && this->numberOfBlocks == other.numberOfBlocks &&
63 this->nextFreeBlockIndex == other.nextFreeBlockIndex;
64}
65
66template<storm::dd::DdType DdType, typename ValueType>
68 uint64_t nextFreeBlockIndex,
69 boost::optional<storm::dd::Add<DdType, ValueType>> const& changedStates) const {
70 return Partition<DdType, ValueType>(newPartitionAdd, blockVariables, numberOfBlocks, nextFreeBlockIndex, changedStates);
71}
72
73template<storm::dd::DdType DdType, typename ValueType>
75 uint64_t nextFreeBlockIndex,
76 boost::optional<storm::dd::Bdd<DdType>> const& changedStates) const {
77 return Partition<DdType, ValueType>(newPartitionBdd, blockVariables, numberOfBlocks, nextFreeBlockIndex, changedStates);
78}
79
80template<storm::dd::DdType DdType, typename ValueType>
81boost::optional<std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>>
83 boost::optional<std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>> result;
84 if (formula.isProbabilityOperatorFormula()) {
85 return extractConstraintTargetFormulas(formula.asProbabilityOperatorFormula().getSubformula());
86 } else if (formula.isRewardOperatorFormula()) {
87 return extractConstraintTargetFormulas(formula.asRewardOperatorFormula().getSubformula());
88 } else if (formula.isUntilFormula()) {
89 storm::logic::UntilFormula const& untilFormula = formula.asUntilFormula();
91 if (untilFormula.getLeftSubformula().isInFragment(propositional) && untilFormula.getRightSubformula().isInFragment(propositional)) {
92 result = std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>();
93 result.get().first = untilFormula.getLeftSubformula().asSharedPointer();
94 result.get().second = untilFormula.getRightSubformula().asSharedPointer();
95 }
96 } else if (formula.isEventuallyFormula()) {
97 storm::logic::EventuallyFormula const& eventuallyFormula = formula.asEventuallyFormula();
99 if (eventuallyFormula.getSubformula().isInFragment(propositional)) {
100 result = std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>();
101 result.get().first = std::make_shared<storm::logic::BooleanLiteralFormula>(true);
102 result.get().second = eventuallyFormula.getSubformula().asSharedPointer();
103 }
104 }
105 return result;
106}
107
108template<storm::dd::DdType DdType, typename ValueType>
110 storm::storage::BisimulationType const& bisimulationType,
111 std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
113
114 boost::optional<std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>> constraintTargetFormulas;
115 if (bisimulationSettings.getInitialPartitionMode() == storm::settings::modules::BisimulationSettings::InitialPartitionMode::Finer && formulas.size() == 1) {
116 constraintTargetFormulas = extractConstraintTargetFormulas(*formulas.front());
117 }
118
119 if (constraintTargetFormulas && bisimulationType == storm::storage::BisimulationType::Strong) {
120 return createDistanceBased(model, *constraintTargetFormulas.get().first, *constraintTargetFormulas.get().second);
121 } else {
122 return create(model, bisimulationType, PreservationInformation<DdType, ValueType>(model, formulas));
123 }
124}
125
126template<storm::dd::DdType DdType, typename ValueType>
128 storm::storage::BisimulationType const& bisimulationType,
129 PreservationInformation<DdType, ValueType> const& preservationInformation) {
130 std::vector<storm::expressions::Expression> expressionVector;
131 for (auto const& expression : preservationInformation.getExpressions()) {
132 expressionVector.emplace_back(expression);
133 }
134
135 return create(model, expressionVector, bisimulationType);
136}
137
138template<storm::dd::DdType DdType, typename ValueType>
140 storm::logic::Formula const& constraintFormula,
141 storm::logic::Formula const& targetFormula) {
143
144 std::unique_ptr<storm::modelchecker::CheckResult> subresult = propositionalChecker.check(constraintFormula);
145 storm::dd::Bdd<DdType> constraintStates = subresult->asSymbolicQualitativeCheckResult<DdType>().getTruthValuesVector();
146 subresult = propositionalChecker.check(targetFormula);
147 storm::dd::Bdd<DdType> targetStates = subresult->asSymbolicQualitativeCheckResult<DdType>().getTruthValuesVector();
148
149 return createDistanceBased(model, constraintStates, targetStates);
150}
151
152template<storm::dd::DdType DdType, typename ValueType>
154 storm::dd::Bdd<DdType> const& constraintStates,
155 storm::dd::Bdd<DdType> const& targetStates) {
156 STORM_LOG_TRACE("Creating distance-based partition.");
157
158 std::pair<storm::expressions::Variable, storm::expressions::Variable> blockVariables = createBlockVariables(model);
159
160 auto start = std::chrono::high_resolution_clock::now();
161
162 // Set up the construction.
163 storm::dd::DdManager<DdType>& manager = model.getManager();
164 storm::dd::Bdd<DdType> partitionBdd = manager.getBddZero();
165 storm::dd::Bdd<DdType> transitionMatrixBdd = model.getTransitionMatrix().notZero().existsAbstract(model.getNondeterminismVariables());
166 storm::dd::Bdd<DdType> coveredStates = manager.getBddZero();
167 uint64_t blockCount = 0;
168
169 // Backward BFS.
170 storm::dd::Bdd<DdType> backwardFrontier = targetStates;
171 while (!backwardFrontier.isZero()) {
172 partitionBdd |= backwardFrontier && manager.getEncoding(blockVariables.first, blockCount++, false);
173 coveredStates |= backwardFrontier;
174 backwardFrontier = backwardFrontier.inverseRelationalProduct(transitionMatrixBdd, model.getRowVariables(), model.getColumnVariables()) &&
175 !coveredStates && constraintStates;
176 }
177
178 // If there are states that cannot reach the target states (via only constraint states) at all, put them in one block.
179 if (coveredStates != model.getReachableStates()) {
180 partitionBdd |= (model.getReachableStates() && !coveredStates) && manager.getEncoding(blockVariables.first, blockCount++, false);
181 }
182
183 // Move the partition over to the primed variables.
184 partitionBdd = partitionBdd.swapVariables(model.getRowColumnMetaVariablePairs());
185
186 auto end = std::chrono::high_resolution_clock::now();
187 STORM_LOG_INFO("Created distance and label-based initial partition in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
188 << "ms.");
189
190 // Store the partition as an ADD only in the case of CUDD.
192 return Partition<DdType, ValueType>(partitionBdd.template toAdd<ValueType>(), blockVariables, blockCount, blockCount);
193 } else {
194 return Partition<DdType, ValueType>(partitionBdd, blockVariables, blockCount, blockCount);
195 }
196}
197
198template<storm::dd::DdType DdType, typename ValueType>
199std::pair<storm::expressions::Variable, storm::expressions::Variable> Partition<DdType, ValueType>::createBlockVariables(
202
203 uint64_t numberOfDdVariables = 0;
204 for (auto const& metaVariable : model.getRowVariables()) {
205 auto const& ddMetaVariable = manager.getMetaVariable(metaVariable);
206 numberOfDdVariables += ddMetaVariable.getNumberOfDdVariables();
207 }
208 if (model.getType() == storm::models::ModelType::Mdp) {
209 auto mdp = model.template as<storm::models::symbolic::Mdp<DdType, ValueType>>();
210 for (auto const& metaVariable : mdp->getNondeterminismVariables()) {
211 auto const& ddMetaVariable = manager.getMetaVariable(metaVariable);
212 numberOfDdVariables += ddMetaVariable.getNumberOfDdVariables();
213 }
214 }
215
216 return createBlockVariables(manager, numberOfDdVariables);
217}
218
219template<storm::dd::DdType DdType, typename ValueType>
221 std::vector<storm::expressions::Expression> const& expressions,
222 storm::storage::BisimulationType const& bisimulationType) {
223 STORM_LOG_THROW(bisimulationType == storm::storage::BisimulationType::Strong, storm::exceptions::NotSupportedException,
224 "Currently only strong bisimulation is supported.");
225
226 std::pair<storm::expressions::Variable, storm::expressions::Variable> blockVariables = createBlockVariables(model);
227
228 std::vector<storm::dd::Bdd<DdType>> stateSets;
229 for (auto const& expression : expressions) {
230 stateSets.emplace_back(model.getStates(expression));
231 }
232 auto start = std::chrono::high_resolution_clock::now();
233 std::pair<storm::dd::Bdd<DdType>, uint64_t> partitionBddAndBlockCount = createPartitionBdd(model.getManager(), model, stateSets, blockVariables.first);
234 auto end = std::chrono::high_resolution_clock::now();
235 STORM_LOG_INFO("Created label-based initial partition in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms.");
236
237 // Store the partition as an ADD only in the case of CUDD.
239 return Partition<DdType, ValueType>(partitionBddAndBlockCount.first.template toAdd<ValueType>(), blockVariables, partitionBddAndBlockCount.second,
240 partitionBddAndBlockCount.second);
241 } else {
242 return Partition<DdType, ValueType>(partitionBddAndBlockCount.first, blockVariables, partitionBddAndBlockCount.second,
243 partitionBddAndBlockCount.second);
244 }
245}
246
247template<storm::dd::DdType DdType, typename ValueType>
250 std::pair<storm::expressions::Variable, storm::expressions::Variable> const& blockVariables) {
251 storm::dd::Bdd<DdType> choicePartitionBdd =
252 (!model.getIllegalMask() && model.getReachableStates()) && model.getManager().getEncoding(blockVariables.first, 0, false);
253
254 // Store the partition as an ADD only in the case of CUDD.
256 return Partition<DdType, ValueType>(choicePartitionBdd.template toAdd<ValueType>(), blockVariables, 1, 1);
257 } else {
258 return Partition<DdType, ValueType>(choicePartitionBdd, blockVariables, 1, 1);
259 }
260}
261
262template<storm::dd::DdType DdType, typename ValueType>
264 return this->getStates().getNonZeroCount();
265}
266
267template<storm::dd::DdType DdType, typename ValueType>
269 if (this->storedAsAdd()) {
270 return this->asAdd().notZero().existsAbstract({this->getBlockVariable()});
271 } else {
272 return this->asBdd().existsAbstract({this->getBlockVariable()});
273 }
274}
275
276template<storm::dd::DdType DdType, typename ValueType>
278 return static_cast<bool>(changedStates);
279}
280
281template<storm::dd::DdType DdType, typename ValueType>
283 return boost::get<storm::dd::Add<DdType, ValueType>>(changedStates.get());
284}
285
286template<storm::dd::DdType DdType, typename ValueType>
288 return boost::get<storm::dd::Bdd<DdType>>(changedStates.get());
289}
290
291template<storm::dd::DdType DdType, typename ValueType>
293 return numberOfBlocks;
294}
295
296template<storm::dd::DdType DdType, typename ValueType>
298 return partition.which() == 1;
299}
300
301template<storm::dd::DdType DdType, typename ValueType>
303 return partition.which() == 0;
304}
305
306template<storm::dd::DdType DdType, typename ValueType>
308 return boost::get<storm::dd::Add<DdType, ValueType>>(partition);
309}
310
311template<storm::dd::DdType DdType, typename ValueType>
313 return boost::get<storm::dd::Bdd<DdType>>(partition);
314}
315
316template<storm::dd::DdType DdType, typename ValueType>
317std::pair<storm::expressions::Variable, storm::expressions::Variable> const& Partition<DdType, ValueType>::getBlockVariables() const {
318 return blockVariables;
319}
320
321template<storm::dd::DdType DdType, typename ValueType>
323 return blockVariables.first;
324}
325
326template<storm::dd::DdType DdType, typename ValueType>
328 return blockVariables.second;
329}
330
331template<storm::dd::DdType DdType, typename ValueType>
333 return nextFreeBlockIndex;
334}
335
336template<storm::dd::DdType DdType, typename ValueType>
338 if (this->storedAsBdd()) {
339 return asBdd().getNodeCount();
340 } else {
341 return asAdd().getNodeCount();
342 }
343}
344
345template<storm::dd::DdType DdType>
346void enumerateBlocksRec(std::vector<storm::dd::Bdd<DdType>> const& stateSets, storm::dd::Bdd<DdType> const& currentStateSet, uint64_t offset,
347 storm::expressions::Variable const& blockVariable, std::function<void(storm::dd::Bdd<DdType> const&)> const& callback) {
348 if (currentStateSet.isZero()) {
349 return;
350 }
351 if (offset == stateSets.size()) {
352 callback(currentStateSet);
353 } else {
354 enumerateBlocksRec(stateSets, currentStateSet && stateSets[offset], offset + 1, blockVariable, callback);
355 enumerateBlocksRec(stateSets, currentStateSet && !stateSets[offset], offset + 1, blockVariable, callback);
356 }
357}
358
359template<storm::dd::DdType DdType, typename ValueType>
360std::pair<storm::dd::Bdd<DdType>, uint64_t> Partition<DdType, ValueType>::createPartitionBdd(storm::dd::DdManager<DdType> const& manager,
362 std::vector<storm::dd::Bdd<DdType>> const& stateSets,
363 storm::expressions::Variable const& blockVariable) {
364 uint64_t blockCount = 0;
365 storm::dd::Bdd<DdType> partitionBdd = manager.getBddZero();
366
367 // Enumerate all realizable blocks.
368 enumerateBlocksRec<DdType>(stateSets, model.getReachableStates(), 0, blockVariable,
369 [&manager, &partitionBdd, &blockVariable, &blockCount](storm::dd::Bdd<DdType> const& stateSet) {
370 partitionBdd |= (stateSet && manager.getEncoding(blockVariable, blockCount, false));
371 blockCount++;
372 });
373
374 // Move the partition over to the primed variables.
375 partitionBdd = partitionBdd.swapVariables(model.getRowColumnMetaVariablePairs());
376
377 return std::make_pair(partitionBdd, blockCount);
378}
379
380template<storm::dd::DdType DdType, typename ValueType>
381std::pair<storm::expressions::Variable, storm::expressions::Variable> Partition<DdType, ValueType>::createBlockVariables(storm::dd::DdManager<DdType>& manager,
382 uint64_t numberOfDdVariables) {
383 std::vector<storm::expressions::Variable> blockVariables;
384 if (manager.hasMetaVariable("blocks")) {
385 int64_t counter = 0;
386 while (manager.hasMetaVariable("block" + std::to_string(counter))) {
387 ++counter;
388 }
389 blockVariables = manager.addBitVectorMetaVariable("blocks" + std::to_string(counter), numberOfDdVariables, 2);
390 } else {
391 blockVariables = manager.addBitVectorMetaVariable("blocks", numberOfDdVariables, 2);
392 }
393 return std::make_pair(blockVariables[0], blockVariables[1]);
394}
395
396template class Partition<storm::dd::DdType::CUDD, double>;
397
398template class Partition<storm::dd::DdType::Sylvan, double>;
399template class Partition<storm::dd::DdType::Sylvan, storm::RationalNumber>;
400template class Partition<storm::dd::DdType::Sylvan, storm::RationalFunction>;
401
402} // namespace bisimulation
403} // namespace dd
404} // namespace storm
Bdd< LibraryType > notZero() const
Computes a BDD that represents the function in which all assignments with a function value unequal to...
Definition Add.cpp:431
Bdd< LibraryType > existsAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Existentially abstracts from the given meta variables.
Definition Bdd.cpp:178
Bdd< LibraryType > inverseRelationalProduct(Bdd< LibraryType > const &relation, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables) const
Computes the inverse relational product of the current BDD and the given BDD representing a relation.
Definition Bdd.cpp:246
bool isZero() const
Retrieves whether this DD represents the constant zero function.
Definition Bdd.cpp:547
Bdd< LibraryType > swapVariables(std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &metaVariablePairs) const
Swaps the given pairs of meta variables in the BDD.
Definition Bdd.cpp:302
static Partition createTrivialChoicePartition(storm::models::symbolic::NondeterministicModel< DdType, ValueType > const &model, std::pair< storm::expressions::Variable, storm::expressions::Variable > const &blockVariables)
storm::expressions::Variable const & getBlockVariable() const
bool hasChangedStates() const
Retrieves whether this partition has information about the states whose partition block assignment ch...
storm::dd::Bdd< DdType > const & asBdd() const
storm::expressions::Variable const & getPrimedBlockVariable() const
storm::dd::Bdd< DdType > getStates() const
bool operator==(Partition< DdType, ValueType > const &other) const
Definition Partition.cpp:61
storm::dd::Add< DdType, ValueType > const & changedStatesAsAdd() const
Retrieves the DD representing the states whose partition block assignment changed.
static Partition create(storm::models::symbolic::Model< DdType, ValueType > const &model, storm::storage::BisimulationType const &bisimulationType, PreservationInformation< DdType, ValueType > const &preservationInformation)
std::pair< storm::expressions::Variable, storm::expressions::Variable > const & getBlockVariables() const
storm::dd::Bdd< DdType > const & changedStatesAsBdd() const
storm::dd::Add< DdType, ValueType > const & asAdd() const
Partition< DdType, ValueType > replacePartition(storm::dd::Add< DdType, ValueType > const &newPartitionAdd, uint64_t numberOfBlocks, uint64_t nextFreeBlockIndex, boost::optional< storm::dd::Add< DdType, ValueType > > const &changedStates=boost::none) const
Definition Partition.cpp:67
std::set< storm::expressions::Expression > const & getExpressions() const
Formula const & getRightSubformula() const
Formula const & getLeftSubformula() const
RewardOperatorFormula & asRewardOperatorFormula()
Definition Formula.cpp:461
UntilFormula & asUntilFormula()
Definition Formula.cpp:317
virtual bool isProbabilityOperatorFormula() const
Definition Formula.cpp:172
ProbabilityOperatorFormula & asProbabilityOperatorFormula()
Definition Formula.cpp:453
virtual bool isUntilFormula() const
Definition Formula.cpp:80
virtual bool isRewardOperatorFormula() const
Definition Formula.cpp:176
EventuallyFormula & asEventuallyFormula()
Definition Formula.cpp:333
bool isInFragment(FragmentSpecification const &fragment) const
Definition Formula.cpp:196
virtual bool isEventuallyFormula() const
Definition Formula.cpp:88
std::shared_ptr< Formula const > asSharedPointer()
Definition Formula.cpp:548
Formula const & getSubformula() const
Formula const & getSubformula() const
virtual ModelType getType() const
Return the actual type of the model.
Definition ModelBase.cpp:7
Base class for all symbolic models.
Definition Model.h:46
storm::dd::DdManager< Type > & getManager() const
Retrieves the manager responsible for the DDs that represent this model.
Definition Model.cpp:92
storm::dd::Add< Type, ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:177
std::set< storm::expressions::Variable > const & getColumnVariables() const
Retrieves the meta variables used to encode the columns of the transition matrix and the vector indic...
Definition Model.cpp:197
virtual std::set< storm::expressions::Variable > const & getNondeterminismVariables() const
Retrieves all meta variables used to encode the nondeterminism.
Definition Model.cpp:218
std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const & getRowColumnMetaVariablePairs() const
Retrieves the pairs of row and column meta variables.
Definition Model.cpp:223
std::set< storm::expressions::Variable > const & getRowVariables() const
Retrieves the meta variables used to encode the rows of the transition matrix and the vector indices.
Definition Model.cpp:192
virtual storm::dd::Bdd< Type > getStates(std::string const &label) const
Returns the sets of states labeled with the given label.
Definition Model.cpp:117
storm::dd::Bdd< Type > const & getReachableStates() const
Retrieves the reachable states of the model.
Definition Model.cpp:102
Base class for all nondeterministic symbolic models.
storm::dd::Bdd< Type > const & getIllegalMask() const
Retrieves a BDD characterizing all illegal nondeterminism encodings in the model.
#define STORM_LOG_INFO(message)
Definition logging.h:29
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
void enumerateBlocksRec(std::vector< storm::dd::Bdd< DdType > > const &stateSets, storm::dd::Bdd< DdType > const &currentStateSet, uint64_t offset, storm::expressions::Variable const &blockVariable, std::function< void(storm::dd::Bdd< DdType > const &)> const &callback)
FragmentSpecification propositional()
std::pair< storm::RationalNumber, storm::RationalNumber > count(std::vector< storm::storage::BitVector > const &origSets, std::vector< storm::storage::BitVector > const &intersects, std::vector< storm::storage::BitVector > const &intersectsInfo, storm::RationalNumber val, bool plus, uint64_t remdepth)
SettingsType const & getModule()
Get module.
SettingsManager const & manager()
Retrieves the settings manager.
LabParser.cpp.
Definition cli.cpp:18