Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
StateSetAbstractor.cpp
Go to the documentation of this file.
2
8
9namespace storm::gbar {
10namespace abstraction {
11
12template<storm::dd::DdType DdType, typename ValueType>
14 std::vector<storm::expressions::Expression> const& statePredicates,
15 std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory)
16 : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())),
17 abstractionInformation(abstractionInformation),
18 localExpressionInformation(abstractionInformation),
19 relevantPredicatesAndVariables(),
20 concretePredicateVariables(),
21 forceRecomputation(true),
22 cachedBdd(abstractionInformation.getDdManager().getBddOne()),
23 constraint(abstractionInformation.getDdManager().getBddOne()) {
24 for (auto const& constraint : abstractionInformation.getConstraints()) {
25 smtSolver->add(constraint);
26 }
27
28 // Assert all state predicates.
29 for (auto const& predicate : statePredicates) {
30 smtSolver->add(predicate);
31
32 // Extract the variables of the predicate, so we know which variables were used when abstracting.
33 std::set<storm::expressions::Variable> usedVariables = predicate.getVariables();
34 concretePredicateVariables.insert(usedVariables.begin(), usedVariables.end());
35 }
36 localExpressionInformation.relate(concretePredicateVariables);
37}
38
39template<storm::dd::DdType DdType, typename ValueType>
40void StateSetAbstractor<DdType, ValueType>::addMissingPredicates(std::set<uint_fast64_t> const& newRelevantPredicateIndices) {
41 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newPredicateVariables =
42 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables, newRelevantPredicateIndices);
43
44 for (auto const& element : newPredicateVariables) {
45 smtSolver->add(storm::expressions::iff(element.first, this->getAbstractionInformation().getPredicateByIndex(element.second)));
46 decisionVariables.push_back(element.first);
47 }
48
49 relevantPredicatesAndVariables.insert(relevantPredicatesAndVariables.end(), newPredicateVariables.begin(), newPredicateVariables.end());
50 std::sort(relevantPredicatesAndVariables.begin(), relevantPredicatesAndVariables.end(),
51 [](std::pair<storm::expressions::Variable, uint_fast64_t> const& firstPair,
52 std::pair<storm::expressions::Variable, uint_fast64_t> const& secondPair) { return firstPair.second < secondPair.second; });
53}
54
55template<storm::dd::DdType DdType, typename ValueType>
56void StateSetAbstractor<DdType, ValueType>::refine(std::vector<uint_fast64_t> const& newPredicates) {
57 // Make the partition aware of the new predicates, which may make more predicates relevant to the abstraction.
58 for (auto const& predicateIndex : newPredicates) {
59 localExpressionInformation.addExpression(predicateIndex);
60 }
61
62 std::set<uint_fast64_t> newRelevantPredicateIndices = localExpressionInformation.getRelatedExpressions(concretePredicateVariables);
63
64 // Since the number of relevant predicates is monotonic, we can simply check for the size here.
65 STORM_LOG_ASSERT(newRelevantPredicateIndices.size() >= relevantPredicatesAndVariables.size(), "Illegal size of relevant predicates.");
66 if (newRelevantPredicateIndices.size() > relevantPredicatesAndVariables.size()) {
67 // Before adding the missing predicates, we need to remove the constraint BDD.
68 this->popConstraintBdd();
69
70 // If we need to recompute the BDD, we start by introducing decision variables and the corresponding
71 // constraints in the SMT problem.
72 addMissingPredicates(newRelevantPredicateIndices);
73
74 // Then re-add the constraint BDD.
75 this->pushConstraintBdd();
76 forceRecomputation = true;
77 }
78}
79
80template<storm::dd::DdType DdType, typename ValueType>
82 smtSolver->add(constraint);
83}
84
85template<storm::dd::DdType DdType, typename ValueType>
87 // If the constraint is different from the last one, we add it to the solver.
88 if (newConstraint != this->constraint) {
89 constraint = newConstraint;
90 this->pushConstraintBdd();
91 }
92}
93
94template<storm::dd::DdType DdType, typename ValueType>
96 storm::dd::Bdd<DdType> result = this->getAbstractionInformation().getDdManager().getBddOne();
97 for (auto const& variableIndexPair : relevantPredicatesAndVariables) {
98 if (model.getBooleanValue(variableIndexPair.first)) {
99 result &= this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
100 } else {
101 result &= !this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
102 }
103 }
104 return result;
105}
106
107template<storm::dd::DdType DdType, typename ValueType>
108void StateSetAbstractor<DdType, ValueType>::recomputeCachedBdd() {
109 STORM_LOG_TRACE("Recomputing BDD for state set abstraction.");
110
111 storm::dd::Bdd<DdType> result = this->getAbstractionInformation().getDdManager().getBddZero();
112 smtSolver->allSat(decisionVariables, [&result, this](storm::solver::SmtSolver::ModelReference const& model) {
113 result |= getStateBdd(model);
114 return true;
115 });
116
117 cachedBdd = result;
118}
119
120template<storm::dd::DdType DdType, typename ValueType>
121void StateSetAbstractor<DdType, ValueType>::popConstraintBdd() {
122 // If the last constraint was not the constant one BDD, we need to pop the constraint from the solver.
123 if (this->constraint.isOne()) {
124 return;
125 }
126 smtSolver->pop();
127}
128
129template<storm::dd::DdType DdType, typename ValueType>
130void StateSetAbstractor<DdType, ValueType>::pushConstraintBdd() {
131 if (this->constraint.isOne()) {
132 return;
133 }
134
135 // Create a new backtracking point before adding the constraint.
136 smtSolver->push();
137
138 // Create the constraint.
139 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result =
140 constraint.toExpression(this->getAbstractionInformation().getExpressionManager());
141
142 // Then add the constraint.
143 for (auto const& expression : result.first) {
144 smtSolver->add(expression);
145 }
146
147 // Finally associate the level variables with the predicates.
148 for (auto const& indexVariablePair : result.second) {
149 smtSolver->add(
150 storm::expressions::iff(indexVariablePair.second, this->getAbstractionInformation().getPredicateForDdVariableIndex(indexVariablePair.first)));
151 }
152}
153
154template<storm::dd::DdType DdType, typename ValueType>
156 if (forceRecomputation) {
157 this->recomputeCachedBdd();
158 }
159 return cachedBdd;
160}
161
162template<storm::dd::DdType DdType, typename ValueType>
164 return abstractionInformation.get();
165}
166
167template<storm::dd::DdType DdType, typename ValueType>
168AbstractionInformation<DdType> const& StateSetAbstractor<DdType, ValueType>::getAbstractionInformation() const {
169 return abstractionInformation.get();
170}
171
172template class StateSetAbstractor<storm::dd::DdType::CUDD, double>;
173template class StateSetAbstractor<storm::dd::DdType::Sylvan, double>;
174template class StateSetAbstractor<storm::dd::DdType::Sylvan, storm::RationalNumber>;
175} // namespace abstraction
176} // namespace storm::gbar
std::pair< std::vector< storm::expressions::Expression >, std::unordered_map< uint_fast64_t, storm::expressions::Variable > > toExpression(storm::expressions::ExpressionManager &manager) const
Translates the function the BDD is representing to a set of expressions that characterize the functio...
Definition Bdd.cpp:496
DdManager< LibraryType > & getDdManager() const
Retrieves the manager that is responsible for this DD.
Definition Dd.cpp:38
std::vector< storm::expressions::Expression > const & getConstraints() const
Retrieves a list of expressions that constrain the valid variable values.
void constrain(storm::expressions::Expression const &constraint)
Constrains the abstract states with the given expression.
void refine(std::vector< uint_fast64_t > const &newPredicateIndices)
Refines the abstractor by making the given predicates new abstract predicates.
storm::dd::Bdd< DdType > getAbstractStates()
Retrieves the set of abstract states matching all predicates added to this abstractor.
StateSetAbstractor(StateSetAbstractor const &other)=default
The base class for all model references.
Definition SmtSolver.h:31
virtual bool getBooleanValue(storm::expressions::Variable const &variable) const =0
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
Expression iff(Expression const &first, Expression const &second)