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