25template<storm::dd::DdType DdType,
typename ValueType>
27 std::shared_ptr<storm::utility::solver::SmtSolverFactory>
const& smtSolverFactory,
31 smtSolverFactory(smtSolverFactory),
32 abstractionInformation(env, model.getManager(), model.getAllExpressionVariables(), smtSolverFactory->create(model.getManager()),
35 initialStateAbstractor(abstractionInformation, {model.getInitialStatesExpression()}, this->smtSolverFactory),
36 restrictToValidBlocks(
false),
37 validBlockAbstractor(abstractionInformation, smtSolverFactory),
39 refinementPerformed(
true) {
41 STORM_LOG_WARN_COND(model.isLinear(),
"The model appears to contain non-linear expressions, which may cause malfunctioning of the abstraction.");
45 STORM_LOG_THROW(model.getNumberOfAutomata() == 1, storm::exceptions::WrongFormatException,
46 "Cannot create abstract model from program containing more than one automaton.");
49 for (
auto const& range : this->model.get().getAllRangeExpressions()) {
50 abstractionInformation.addConstraint(range);
51 initialStateAbstractor.constrain(range);
52 validBlockAbstractor.constrain(range);
55 uint_fast64_t totalNumberOfEdges = 0;
56 uint_fast64_t maximalDestinationCount = 0;
57 std::vector<storm::expressions::Expression> allGuards;
58 for (
auto const& automaton : model.getAutomata()) {
59 for (
auto const& edge : automaton.getEdges()) {
60 maximalDestinationCount = std::max(maximalDestinationCount,
static_cast<uint_fast64_t
>(edge.getNumberOfDestinations()));
63 totalNumberOfEdges += automaton.getNumberOfEdges();
69 abstractionInformation.createEncodingVariables(
static_cast<uint_fast64_t
>(std::ceil(std::log2(totalNumberOfEdges))), 64,
70 static_cast<uint_fast64_t
>(std::ceil(std::log2(maximalDestinationCount))));
73 bool useDecomposition = options.useDecomposition;
74 restrictToValidBlocks = options.restrictToValidBlocks;
75 bool addPredicatesForValidBlocks = !restrictToValidBlocks;
76 bool debug = options.debug;
77 for (
auto const& automaton : model.getAutomata()) {
78 automata.emplace_back(automaton, abstractionInformation, this->smtSolverFactory, useDecomposition, addPredicatesForValidBlocks, debug);
82 initialLocationsBdd = automata.front().getInitialLocationsBdd();
83 edgeDecoratorAdd = automata.front().getEdgeDecoratorAdd();
86template<storm::dd::DdType DdType,
typename ValueType>
88 return abstractionInformation.getDdManager();
91template<storm::dd::DdType DdType,
typename ValueType>
94 std::vector<uint_fast64_t> predicateIndices;
96 STORM_LOG_THROW(predicate.hasBooleanType(), storm::exceptions::InvalidArgumentException,
"Expecting a predicate of type bool.");
97 predicateIndices.push_back(abstractionInformation.getOrAddPredicate(predicate));
101 for (
auto& automaton : automata) {
102 automaton.refine(predicateIndices);
106 initialStateAbstractor.refine(predicateIndices);
108 if (this->restrictToValidBlocks) {
110 validBlockAbstractor.refine(predicateIndices);
116template<storm::dd::DdType DdType,
typename ValueType>
118 if (refinementPerformed) {
119 currentGame = buildGame();
120 refinementPerformed =
false;
125template<storm::dd::DdType DdType,
typename ValueType>
127 return abstractionInformation;
130template<storm::dd::DdType DdType,
typename ValueType>
132 return automata.front().getGuard(player1Choice);
135template<storm::dd::DdType DdType,
typename ValueType>
137 return automata.front().getNumberOfUpdates(player1Choice);
140template<storm::dd::DdType DdType,
typename ValueType>
142 uint64_t player1Choice, uint64_t auxiliaryChoice)
const {
143 return automata.front().getVariableUpdates(player1Choice, auxiliaryChoice);
146template<storm::dd::DdType DdType,
typename ValueType>
148 return automata.front().getAssignedVariables(player1Choice);
151template<storm::dd::DdType DdType,
typename ValueType>
153 return std::make_pair(0, automata.front().getNumberOfEdges());
156template<storm::dd::DdType DdType,
typename ValueType>
158 return model.get().getInitialStatesExpression({model.get().getAutomaton(0)});
161template<storm::dd::DdType DdType,
typename ValueType>
164 smtSolverFactory->create(abstractionInformation.getExpressionManager()));
168template<storm::dd::DdType DdType,
typename ValueType>
169std::unique_ptr<MenuGame<DdType, ValueType>> JaniMenuGameAbstractor<DdType, ValueType>::buildGame() {
174 game.
bdd &= edgeDecoratorAdd.notZero();
177 std::set<storm::expressions::Variable> variablesToAbstract(abstractionInformation.getPlayer1VariableSet(abstractionInformation.getPlayer1VariableCount()));
178 std::set<storm::expressions::Variable> successorAndAuxVariables(abstractionInformation.getSuccessorVariables());
180 variablesToAbstract.insert(player2Variables.begin(), player2Variables.end());
181 auto auxVariables = abstractionInformation.getAuxVariableSet(0, abstractionInformation.getAuxVariableCount());
182 variablesToAbstract.insert(auxVariables.begin(), auxVariables.end());
183 successorAndAuxVariables.insert(auxVariables.begin(), auxVariables.end());
187 if (this->isRestrictToRelevantStatesSet()) {
189 for (
auto const& expression : this->terminalStateExpressions) {
190 nonTerminalStates &= !this->getStates(expression);
192 if (this->hasTargetStateExpression()) {
193 nonTerminalStates &= !this->getStates(this->getTargetStateExpression());
196 relevantStatesWatch.stop();
200 if (this->restrictToValidBlocks) {
205 auto choicesWithOnlyValidSuccessors =
206 !game.
bdd.
andExists(!validBlocks.
swapVariables(abstractionInformation.getSourceSuccessorVariablePairs()), successorAndAuxVariables) &&
210 extendedTransitionRelation &= validBlocks && choicesWithOnlyValidSuccessors;
211 initialStates &= validBlocks;
216 initialStates.
addMetaVariables(abstractionInformation.getSourcePredicateVariables());
219 abstractionInformation.getSuccessorVariables())
222 relevantStatesWatch.start();
223 if (this->isRestrictToRelevantStatesSet() && this->hasTargetStateExpression()) {
225 storm::dd::Bdd<DdType> targetStates = reachableStates && this->getStates(this->getTargetStateExpression());
229 targetStates, reachableStates, transitionRelation, abstractionInformation.getSourceVariables(), abstractionInformation.getSuccessorVariables());
234 (reachableStates && !targetStates)
235 .relationalProduct(transitionRelation, abstractionInformation.getSourceVariables(), abstractionInformation.getSuccessorVariables());
238 transitionRelation &= reachableStates && reachableStates.
swapVariables(abstractionInformation.getExtendedSourceSuccessorVariablePairs());
240 relevantStatesWatch.stop();
241 STORM_LOG_TRACE(
"Restricting to relevant states took " << relevantStatesWatch.getTimeInMilliseconds() <<
"ms.");
246 storm::dd::Bdd<DdType> deadlockStates = transitionRelation.
existsAbstract(abstractionInformation.getSuccessorVariables());
247 deadlockStates = reachableStates && !deadlockStates;
250 storm::dd::Add<DdType, ValueType> deadlockTransitions = abstractionInformation.
getDdManager().template getAddZero<ValueType>();
251 if (!deadlockStates.
isZero()) {
252 deadlockTransitions = (deadlockStates && abstractionInformation.getAllPredicateIdentities() && abstractionInformation.getAllLocationIdentities() &&
253 abstractionInformation.encodePlayer1Choice(0, abstractionInformation.getPlayer1VariableCount()) &&
255 abstractionInformation.encodeAux(0, 0, abstractionInformation.getAuxVariableCount()))
256 .template toAdd<ValueType>();
260 BottomStateResult<DdType> bottomStateResult(abstractionInformation.getDdManager().getBddZero(), abstractionInformation.getDdManager().getBddZero());
262 bool hasBottomStates = !bottomStateResult.states.isZero();
267 storm::dd::Add<DdType, ValueType> transitionMatrix =
268 (extendedTransitionRelation && reachableStates && reachableStates.
swapVariables(abstractionInformation.getExtendedSourceSuccessorVariablePairs()))
269 .template toAdd<ValueType>();
270 transitionMatrix *= edgeDecoratorAdd;
271 transitionMatrix += deadlockTransitions;
275 (abstractionInformation.getBottomStateBdd(
true,
true) && abstractionInformation.getBottomStateBdd(
false,
true)).template toAdd<ValueType>();
276 reachableStates &= abstractionInformation.getBottomStateBdd(
true,
true);
277 initialStates &= abstractionInformation.getBottomStateBdd(
true,
true);
280 if (hasBottomStates) {
281 transitionMatrix += bottomStateResult.transitions.template toAdd<ValueType>();
282 reachableStates |= bottomStateResult.states;
285 std::set<storm::expressions::Variable> allNondeterminismVariables = player2Variables;
286 allNondeterminismVariables.insert(abstractionInformation.getPlayer1Variables().begin(), abstractionInformation.getPlayer1Variables().end());
288 std::set<storm::expressions::Variable> allSourceVariables(abstractionInformation.getSourceVariables());
289 allSourceVariables.insert(abstractionInformation.getBottomStateVariable(
true));
290 std::set<storm::expressions::Variable> allSuccessorVariables(abstractionInformation.getSuccessorVariables());
291 allSuccessorVariables.insert(abstractionInformation.getBottomStateVariable(
false));
293 return std::make_unique<MenuGame<DdType, ValueType>>(
294 abstractionInformation.getDdManagerAsSharedPointer(), reachableStates, initialStates, abstractionInformation.getDdManager().getBddZero(),
295 transitionMatrix, bottomStateResult.states, allSourceVariables, allSuccessorVariables, abstractionInformation.getExtendedSourceSuccessorVariablePairs(),
296 std::set<storm::expressions::Variable>(abstractionInformation.getPlayer1Variables().begin(), abstractionInformation.getPlayer1Variables().end()),
297 player2Variables, allNondeterminismVariables, auxVariables, abstractionInformation.getPredicateToBddMap());
300template<storm::dd::DdType DdType,
typename ValueType>
303 this->
exportToDot(*currentGame, filename, highlightStates, filter);
306template<storm::dd::DdType DdType,
typename ValueType>
308 return abstractionInformation.getNumberOfPredicates();
311template<storm::dd::DdType DdType,
typename ValueType>
313 terminalStateExpressions.emplace_back(expression);
316template<storm::dd::DdType DdType,
typename ValueType>
318 for (
auto& automaton : automata) {
319 automaton.notifyGuardsArePredicates();
Bdd< LibraryType > existsAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Existentially abstracts from the given meta variables.
bool isZero() const
Retrieves whether this DD represents the constant zero function.
Bdd< LibraryType > andExists(Bdd< LibraryType > const &other, std::set< storm::expressions::Variable > const &existentialVariables) const
Computes the logical and of the current and the given BDD and existentially abstracts from the given ...
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.
void addMetaVariables(std::set< storm::expressions::Variable > const &metaVariables)
Adds the given set of meta variables to the DD.
DdManager< LibraryType > & getDdManager() const
Retrieves the manager that is responsible for this DD.
storm::dd::Bdd< DdType > translate(storm::expressions::Expression const &expression)
std::vector< storm::expressions::Expression > const & getPredicates() const
A class that provides convenience operations to display run times.
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
storm::dd::Bdd< Type > computeBackwardsReachableStates(storm::dd::Bdd< Type > const &initialStates, storm::dd::Bdd< Type > const &constraintStates, storm::dd::Bdd< Type > const &transitions, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables)
std::pair< storm::dd::Bdd< Type >, uint64_t > computeReachableStates(storm::dd::Bdd< Type > const &initialStates, storm::dd::Bdd< Type > const &transitions, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables)
Options that configure the game-based abstraction-refinement procedure.
uint_fast64_t numberOfPlayer2Variables
storm::dd::Bdd< DdType > bdd