Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
Partition.cpp
Go to the documentation of this file.
2
15
16namespace storm {
17namespace dd {
18namespace bisimulation {
19
20template<storm::dd::DdType DdType, typename ValueType>
21Partition<DdType, ValueType>::Partition() : nextFreeBlockIndex(0) {
22 // Intentionally left empty.
23}
24
25template<storm::dd::DdType DdType, typename ValueType>
27 std::pair<storm::expressions::Variable, storm::expressions::Variable> const& blockVariables, uint64_t numberOfBlocks,
28 uint64_t nextFreeBlockIndex, boost::optional<storm::dd::Add<DdType, ValueType>> const& changedStates)
29 : partition(partitionAdd),
30 changedStates(changedStates),
31 blockVariables(blockVariables),
32 numberOfBlocks(numberOfBlocks),
33 nextFreeBlockIndex(nextFreeBlockIndex) {
34 // Intentionally left empty.
35}
36
37template<storm::dd::DdType DdType, typename ValueType>
39 std::pair<storm::expressions::Variable, storm::expressions::Variable> const& blockVariables, uint64_t numberOfBlocks,
40 uint64_t nextFreeBlockIndex, boost::optional<storm::dd::Bdd<DdType>> const& changedStates)
41 : partition(partitionBdd),
42 changedStates(changedStates),
43 blockVariables(blockVariables),
44 numberOfBlocks(numberOfBlocks),
45 nextFreeBlockIndex(nextFreeBlockIndex) {
46 // Intentionally left empty.
47}
48
49template<storm::dd::DdType DdType, typename ValueType>
51 return this->partition == other.partition && this->blockVariables == other.blockVariables && this->numberOfBlocks == other.numberOfBlocks &&
52 this->nextFreeBlockIndex == other.nextFreeBlockIndex;
53}
54
55template<storm::dd::DdType DdType, typename ValueType>
57 uint64_t nextFreeBlockIndex,
58 boost::optional<storm::dd::Add<DdType, ValueType>> const& changedStates) const {
59 return Partition<DdType, ValueType>(newPartitionAdd, blockVariables, numberOfBlocks, nextFreeBlockIndex, changedStates);
60}
61
62template<storm::dd::DdType DdType, typename ValueType>
64 uint64_t nextFreeBlockIndex,
65 boost::optional<storm::dd::Bdd<DdType>> const& changedStates) const {
66 return Partition<DdType, ValueType>(newPartitionBdd, blockVariables, numberOfBlocks, nextFreeBlockIndex, changedStates);
67}
68
69template<storm::dd::DdType DdType, typename ValueType>
70boost::optional<std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>>
72 boost::optional<std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>> result;
73 if (formula.isProbabilityOperatorFormula()) {
74 return extractConstraintTargetFormulas(formula.asProbabilityOperatorFormula().getSubformula());
75 } else if (formula.isRewardOperatorFormula()) {
76 return extractConstraintTargetFormulas(formula.asRewardOperatorFormula().getSubformula());
77 } else if (formula.isUntilFormula()) {
78 storm::logic::UntilFormula const& untilFormula = formula.asUntilFormula();
80 if (untilFormula.getLeftSubformula().isInFragment(propositional) && untilFormula.getRightSubformula().isInFragment(propositional)) {
81 result = std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>();
82 result.get().first = untilFormula.getLeftSubformula().asSharedPointer();
83 result.get().second = untilFormula.getRightSubformula().asSharedPointer();
84 }
85 } else if (formula.isEventuallyFormula()) {
86 storm::logic::EventuallyFormula const& eventuallyFormula = formula.asEventuallyFormula();
88 if (eventuallyFormula.getSubformula().isInFragment(propositional)) {
89 result = std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>();
90 result.get().first = std::make_shared<storm::logic::BooleanLiteralFormula>(true);
91 result.get().second = eventuallyFormula.getSubformula().asSharedPointer();
92 }
93 }
94 return result;
95}
96
97template<storm::dd::DdType DdType, typename ValueType>
99 storm::storage::BisimulationType const& bisimulationType,
100 std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
101 auto const& bisimulationSettings = storm::settings::getModule<storm::settings::modules::BisimulationSettings>();
102
103 boost::optional<std::pair<std::shared_ptr<storm::logic::Formula const>, std::shared_ptr<storm::logic::Formula const>>> constraintTargetFormulas;
104 if (bisimulationSettings.getInitialPartitionMode() == storm::settings::modules::BisimulationSettings::InitialPartitionMode::Finer && formulas.size() == 1) {
105 constraintTargetFormulas = extractConstraintTargetFormulas(*formulas.front());
106 }
107
108 if (constraintTargetFormulas && bisimulationType == storm::storage::BisimulationType::Strong) {
109 return createDistanceBased(model, *constraintTargetFormulas.get().first, *constraintTargetFormulas.get().second);
110 } else {
111 return create(model, bisimulationType, PreservationInformation<DdType, ValueType>(model, formulas));
112 }
113}
114
115template<storm::dd::DdType DdType, typename ValueType>
117 storm::storage::BisimulationType const& bisimulationType,
118 PreservationInformation<DdType, ValueType> const& preservationInformation) {
119 std::vector<storm::expressions::Expression> expressionVector;
120 for (auto const& expression : preservationInformation.getExpressions()) {
121 expressionVector.emplace_back(expression);
122 }
123
124 return create(model, expressionVector, bisimulationType);
125}
126
127template<storm::dd::DdType DdType, typename ValueType>
129 storm::logic::Formula const& constraintFormula,
130 storm::logic::Formula const& targetFormula) {
132
133 std::unique_ptr<storm::modelchecker::CheckResult> subresult = propositionalChecker.check(constraintFormula);
134 storm::dd::Bdd<DdType> constraintStates = subresult->asSymbolicQualitativeCheckResult<DdType>().getTruthValuesVector();
135 subresult = propositionalChecker.check(targetFormula);
136 storm::dd::Bdd<DdType> targetStates = subresult->asSymbolicQualitativeCheckResult<DdType>().getTruthValuesVector();
137
138 return createDistanceBased(model, constraintStates, targetStates);
139}
140
141template<storm::dd::DdType DdType, typename ValueType>
143 storm::dd::Bdd<DdType> const& constraintStates,
144 storm::dd::Bdd<DdType> const& targetStates) {
145 STORM_LOG_TRACE("Creating distance-based partition.");
146
147 std::pair<storm::expressions::Variable, storm::expressions::Variable> blockVariables = createBlockVariables(model);
148
149 auto start = std::chrono::high_resolution_clock::now();
150
151 // Set up the construction.
152 storm::dd::DdManager<DdType>& manager = model.getManager();
153 storm::dd::Bdd<DdType> partitionBdd = manager.getBddZero();
154 storm::dd::Bdd<DdType> transitionMatrixBdd = model.getTransitionMatrix().notZero().existsAbstract(model.getNondeterminismVariables());
155 storm::dd::Bdd<DdType> coveredStates = manager.getBddZero();
156 uint64_t blockCount = 0;
157
158 // Backward BFS.
159 storm::dd::Bdd<DdType> backwardFrontier = targetStates;
160 while (!backwardFrontier.isZero()) {
161 partitionBdd |= backwardFrontier && manager.getEncoding(blockVariables.first, blockCount++, false);
162 coveredStates |= backwardFrontier;
163 backwardFrontier = backwardFrontier.inverseRelationalProduct(transitionMatrixBdd, model.getRowVariables(), model.getColumnVariables()) &&
164 !coveredStates && constraintStates;
165 }
166
167 // If there are states that cannot reach the target states (via only constraint states) at all, put them in one block.
168 if (coveredStates != model.getReachableStates()) {
169 partitionBdd |= (model.getReachableStates() && !coveredStates) && manager.getEncoding(blockVariables.first, blockCount++, false);
170 }
171
172 // Move the partition over to the primed variables.
173 partitionBdd = partitionBdd.swapVariables(model.getRowColumnMetaVariablePairs());
174
175 auto end = std::chrono::high_resolution_clock::now();
176 STORM_LOG_INFO("Created distance and label-based initial partition in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
177 << "ms.");
178
179 // Store the partition as an ADD only in the case of CUDD.
181 return Partition<DdType, ValueType>(partitionBdd.template toAdd<ValueType>(), blockVariables, blockCount, blockCount);
182 } else {
183 return Partition<DdType, ValueType>(partitionBdd, blockVariables, blockCount, blockCount);
184 }
185}
186
187template<storm::dd::DdType DdType, typename ValueType>
188std::pair<storm::expressions::Variable, storm::expressions::Variable> Partition<DdType, ValueType>::createBlockVariables(
191
192 uint64_t numberOfDdVariables = 0;
193 for (auto const& metaVariable : model.getRowVariables()) {
194 auto const& ddMetaVariable = manager.getMetaVariable(metaVariable);
195 numberOfDdVariables += ddMetaVariable.getNumberOfDdVariables();
196 }
197 if (model.getType() == storm::models::ModelType::Mdp) {
198 auto mdp = model.template as<storm::models::symbolic::Mdp<DdType, ValueType>>();
199 for (auto const& metaVariable : mdp->getNondeterminismVariables()) {
200 auto const& ddMetaVariable = manager.getMetaVariable(metaVariable);
201 numberOfDdVariables += ddMetaVariable.getNumberOfDdVariables();
202 }
203 }
204
205 return createBlockVariables(manager, numberOfDdVariables);
206}
207
208template<storm::dd::DdType DdType, typename ValueType>
210 std::vector<storm::expressions::Expression> const& expressions,
211 storm::storage::BisimulationType const& bisimulationType) {
212 STORM_LOG_THROW(bisimulationType == storm::storage::BisimulationType::Strong, storm::exceptions::NotSupportedException,
213 "Currently only strong bisimulation is supported.");
214
215 std::pair<storm::expressions::Variable, storm::expressions::Variable> blockVariables = createBlockVariables(model);
216
217 std::vector<storm::dd::Bdd<DdType>> stateSets;
218 for (auto const& expression : expressions) {
219 stateSets.emplace_back(model.getStates(expression));
220 }
221 auto start = std::chrono::high_resolution_clock::now();
222 std::pair<storm::dd::Bdd<DdType>, uint64_t> partitionBddAndBlockCount = createPartitionBdd(model.getManager(), model, stateSets, blockVariables.first);
223 auto end = std::chrono::high_resolution_clock::now();
224 STORM_LOG_INFO("Created label-based initial partition in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms.");
225
226 // Store the partition as an ADD only in the case of CUDD.
228 return Partition<DdType, ValueType>(partitionBddAndBlockCount.first.template toAdd<ValueType>(), blockVariables, partitionBddAndBlockCount.second,
229 partitionBddAndBlockCount.second);
230 } else {
231 return Partition<DdType, ValueType>(partitionBddAndBlockCount.first, blockVariables, partitionBddAndBlockCount.second,
232 partitionBddAndBlockCount.second);
233 }
234}
235
236template<storm::dd::DdType DdType, typename ValueType>
239 std::pair<storm::expressions::Variable, storm::expressions::Variable> const& blockVariables) {
240 storm::dd::Bdd<DdType> choicePartitionBdd =
241 (!model.getIllegalMask() && model.getReachableStates()) && model.getManager().getEncoding(blockVariables.first, 0, false);
242
243 // Store the partition as an ADD only in the case of CUDD.
245 return Partition<DdType, ValueType>(choicePartitionBdd.template toAdd<ValueType>(), blockVariables, 1, 1);
246 } else {
247 return Partition<DdType, ValueType>(choicePartitionBdd, blockVariables, 1, 1);
248 }
249}
250
251template<storm::dd::DdType DdType, typename ValueType>
253 return this->getStates().getNonZeroCount();
254}
255
256template<storm::dd::DdType DdType, typename ValueType>
258 if (this->storedAsAdd()) {
259 return this->asAdd().notZero().existsAbstract({this->getBlockVariable()});
260 } else {
261 return this->asBdd().existsAbstract({this->getBlockVariable()});
262 }
263}
264
265template<storm::dd::DdType DdType, typename ValueType>
267 return static_cast<bool>(changedStates);
268}
269
270template<storm::dd::DdType DdType, typename ValueType>
272 return boost::get<storm::dd::Add<DdType, ValueType>>(changedStates.get());
273}
274
275template<storm::dd::DdType DdType, typename ValueType>
277 return boost::get<storm::dd::Bdd<DdType>>(changedStates.get());
278}
279
280template<storm::dd::DdType DdType, typename ValueType>
282 return numberOfBlocks;
283}
284
285template<storm::dd::DdType DdType, typename ValueType>
287 return partition.which() == 1;
288}
289
290template<storm::dd::DdType DdType, typename ValueType>
292 return partition.which() == 0;
293}
294
295template<storm::dd::DdType DdType, typename ValueType>
297 return boost::get<storm::dd::Add<DdType, ValueType>>(partition);
298}
299
300template<storm::dd::DdType DdType, typename ValueType>
302 return boost::get<storm::dd::Bdd<DdType>>(partition);
303}
304
305template<storm::dd::DdType DdType, typename ValueType>
306std::pair<storm::expressions::Variable, storm::expressions::Variable> const& Partition<DdType, ValueType>::getBlockVariables() const {
307 return blockVariables;
308}
309
310template<storm::dd::DdType DdType, typename ValueType>
312 return blockVariables.first;
313}
314
315template<storm::dd::DdType DdType, typename ValueType>
317 return blockVariables.second;
318}
319
320template<storm::dd::DdType DdType, typename ValueType>
322 return nextFreeBlockIndex;
323}
324
325template<storm::dd::DdType DdType, typename ValueType>
327 if (this->storedAsBdd()) {
328 return asBdd().getNodeCount();
329 } else {
330 return asAdd().getNodeCount();
331 }
332}
333
334template<storm::dd::DdType DdType>
335void enumerateBlocksRec(std::vector<storm::dd::Bdd<DdType>> const& stateSets, storm::dd::Bdd<DdType> const& currentStateSet, uint64_t offset,
336 storm::expressions::Variable const& blockVariable, std::function<void(storm::dd::Bdd<DdType> const&)> const& callback) {
337 if (currentStateSet.isZero()) {
338 return;
339 }
340 if (offset == stateSets.size()) {
341 callback(currentStateSet);
342 } else {
343 enumerateBlocksRec(stateSets, currentStateSet && stateSets[offset], offset + 1, blockVariable, callback);
344 enumerateBlocksRec(stateSets, currentStateSet && !stateSets[offset], offset + 1, blockVariable, callback);
345 }
346}
347
348template<storm::dd::DdType DdType, typename ValueType>
349std::pair<storm::dd::Bdd<DdType>, uint64_t> Partition<DdType, ValueType>::createPartitionBdd(storm::dd::DdManager<DdType> const& manager,
351 std::vector<storm::dd::Bdd<DdType>> const& stateSets,
352 storm::expressions::Variable const& blockVariable) {
353 uint64_t blockCount = 0;
354 storm::dd::Bdd<DdType> partitionBdd = manager.getBddZero();
355
356 // Enumerate all realizable blocks.
357 enumerateBlocksRec<DdType>(stateSets, model.getReachableStates(), 0, blockVariable,
358 [&manager, &partitionBdd, &blockVariable, &blockCount](storm::dd::Bdd<DdType> const& stateSet) {
359 partitionBdd |= (stateSet && manager.getEncoding(blockVariable, blockCount, false));
360 blockCount++;
361 });
362
363 // Move the partition over to the primed variables.
364 partitionBdd = partitionBdd.swapVariables(model.getRowColumnMetaVariablePairs());
365
366 return std::make_pair(partitionBdd, blockCount);
367}
368
369template<storm::dd::DdType DdType, typename ValueType>
370std::pair<storm::expressions::Variable, storm::expressions::Variable> Partition<DdType, ValueType>::createBlockVariables(storm::dd::DdManager<DdType>& manager,
371 uint64_t numberOfDdVariables) {
372 std::vector<storm::expressions::Variable> blockVariables;
373 if (manager.hasMetaVariable("blocks")) {
374 int64_t counter = 0;
375 while (manager.hasMetaVariable("block" + std::to_string(counter))) {
376 ++counter;
377 }
378 blockVariables = manager.addBitVectorMetaVariable("blocks" + std::to_string(counter), numberOfDdVariables, 2);
379 } else {
380 blockVariables = manager.addBitVectorMetaVariable("blocks", numberOfDdVariables, 2);
381 }
382 return std::make_pair(blockVariables[0], blockVariables[1]);
383}
384
385template class Partition<storm::dd::DdType::CUDD, double>;
386
387template class Partition<storm::dd::DdType::Sylvan, double>;
388template class Partition<storm::dd::DdType::Sylvan, storm::RationalNumber>;
389template class Partition<storm::dd::DdType::Sylvan, storm::RationalFunction>;
390
391} // namespace bisimulation
392} // namespace dd
393} // 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:424
Bdd< LibraryType > existsAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Existentially abstracts from the given meta variables.
Definition Bdd.cpp:172
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:240
bool isZero() const
Retrieves whether this DD represents the constant zero function.
Definition Bdd.cpp:541
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:296
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:50
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:56
std::set< storm::expressions::Expression > const & getExpressions() const
Formula const & getRightSubformula() const
Formula const & getLeftSubformula() const
RewardOperatorFormula & asRewardOperatorFormula()
Definition Formula.cpp:484
UntilFormula & asUntilFormula()
Definition Formula.cpp:325
virtual bool isProbabilityOperatorFormula() const
Definition Formula.cpp:180
ProbabilityOperatorFormula & asProbabilityOperatorFormula()
Definition Formula.cpp:476
virtual bool isUntilFormula() const
Definition Formula.cpp:80
virtual bool isRewardOperatorFormula() const
Definition Formula.cpp:184
EventuallyFormula & asEventuallyFormula()
Definition Formula.cpp:341
bool isInFragment(FragmentSpecification const &fragment) const
Definition Formula.cpp:204
virtual bool isEventuallyFormula() const
Definition Formula.cpp:88
std::shared_ptr< Formula const > asSharedPointer()
Definition Formula.cpp:571
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:42
storm::dd::DdManager< Type > & getManager() const
Retrieves the manager responsible for the DDs that represent this model.
Definition Model.cpp:87
storm::dd::Add< Type, ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:172
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:192
virtual std::set< storm::expressions::Variable > const & getNondeterminismVariables() const
Retrieves all meta variables used to encode the nondeterminism.
Definition Model.cpp:213
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:218
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:187
virtual storm::dd::Bdd< Type > getStates(std::string const &label) const
Returns the sets of states labeled with the given label.
Definition Model.cpp:112
storm::dd::Bdd< Type > const & getReachableStates() const
Retrieves the reachable states of the model.
Definition Model.cpp:97
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:24
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#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)
SettingsManager const & manager()
Retrieves the settings manager.