#include "storm/abstraction/jani/AutomatonAbstractor.h" #include "storm/abstraction/BottomStateResult.h" #include "storm/abstraction/GameBddResult.h" #include "storm/abstraction/AbstractionInformation.h" #include "storm/storage/dd/DdManager.h" #include "storm/storage/dd/Add.h" #include "storm/storage/jani/Automaton.h" #include "storm/storage/jani/Edge.h" #include "storm/settings/SettingsManager.h" #include "storm-config.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/utility/macros.h" namespace storm { namespace abstraction { namespace jani { using storm::settings::modules::AbstractionSettings; template AutomatonAbstractor::AutomatonAbstractor(storm::jani::Automaton const& automaton, AbstractionInformation& abstractionInformation, std::shared_ptr const& smtSolverFactory, bool useDecomposition) : smtSolverFactory(smtSolverFactory), abstractionInformation(abstractionInformation), edges(), automaton(automaton) { // For each concrete command, we create an abstract counterpart. uint64_t edgeId = 0; for (auto const& edge : automaton.getEdges()) { edges.emplace_back(edgeId, edge, abstractionInformation, smtSolverFactory, useDecomposition); ++edgeId; } if (automaton.getNumberOfLocations() > 1) { locationVariables = abstractionInformation.addLocationVariables(automaton.getLocationExpressionVariable(), automaton.getNumberOfLocations() - 1).first; } } template void AutomatonAbstractor::refine(std::vector const& predicates) { for (uint_fast64_t index = 0; index < edges.size(); ++index) { STORM_LOG_TRACE("Refining edge with index " << index << "."); edges[index].refine(predicates); } } template storm::expressions::Expression const& AutomatonAbstractor::getGuard(uint64_t player1Choice) const { return edges[player1Choice].getGuard(); } template uint64_t AutomatonAbstractor::getNumberOfUpdates(uint64_t player1Choice) const { return edges[player1Choice].getNumberOfUpdates(player1Choice); } template std::map AutomatonAbstractor::getVariableUpdates(uint64_t player1Choice, uint64_t auxiliaryChoice) const { return edges[player1Choice].getVariableUpdates(auxiliaryChoice); } template GameBddResult AutomatonAbstractor::abstract() { // First, we retrieve the abstractions of all commands. std::vector> edgeDdsAndUsedOptionVariableCounts; uint_fast64_t maximalNumberOfUsedOptionVariables = 0; for (auto& edge : edges) { edgeDdsAndUsedOptionVariableCounts.push_back(edge.abstract()); maximalNumberOfUsedOptionVariables = std::max(maximalNumberOfUsedOptionVariables, edgeDdsAndUsedOptionVariableCounts.back().numberOfPlayer2Variables); } // Then, we build the module BDD by adding the single command DDs. We need to make sure that all command // DDs use the same amount DD variable encoding the choices of player 2. storm::dd::Bdd result = this->getAbstractionInformation().getDdManager().getBddZero(); for (auto const& edgeDd : edgeDdsAndUsedOptionVariableCounts) { result |= edgeDd.bdd && this->getAbstractionInformation().encodePlayer2Choice(1, edgeDd.numberOfPlayer2Variables, maximalNumberOfUsedOptionVariables); } return GameBddResult(result, maximalNumberOfUsedOptionVariables); } template BottomStateResult AutomatonAbstractor::getBottomStateTransitions(storm::dd::Bdd const& reachableStates, uint_fast64_t numberOfPlayer2Variables) { BottomStateResult result(this->getAbstractionInformation().getDdManager().getBddZero(), this->getAbstractionInformation().getDdManager().getBddZero()); for (auto& edge : edges) { BottomStateResult commandBottomStateResult = edge.getBottomStateTransitions(reachableStates, numberOfPlayer2Variables, locationVariables); result.states |= commandBottomStateResult.states; result.transitions |= commandBottomStateResult.transitions; } return result; } template storm::dd::Add AutomatonAbstractor::getEdgeDecoratorAdd() const { storm::dd::Add result = this->getAbstractionInformation().getDdManager().template getAddZero(); for (auto const& edge : edges) { result += edge.getEdgeDecoratorAdd(locationVariables); } return result; } template storm::dd::Bdd AutomatonAbstractor::getInitialLocationsBdd() const { if (automaton.get().getNumberOfLocations() == 1) { return this->getAbstractionInformation().getDdManager().getBddOne(); } std::set const& initialLocationIndices = automaton.get().getInitialLocationIndices(); storm::dd::Bdd result = this->getAbstractionInformation().getDdManager().getBddZero(); for (auto const& initialLocationIndex : initialLocationIndices) { result |= this->getAbstractionInformation().encodeLocation(locationVariables.get().first, initialLocationIndex); } return result; } template std::vector> const& AutomatonAbstractor::getEdges() const { return edges; } template std::vector>& AutomatonAbstractor::getEdges() { return edges; } template std::size_t AutomatonAbstractor::getNumberOfEdges() const { return edges.size(); } template AbstractionInformation const& AutomatonAbstractor::getAbstractionInformation() const { return abstractionInformation.get(); } template class AutomatonAbstractor; template class AutomatonAbstractor; #ifdef STORM_HAVE_CARL template class AutomatonAbstractor; #endif } } }