#include "storm/abstraction/jani/AutomatonAbstractor.h" #include "storm/abstraction/AbstractionInformation.h" #include "storm/abstraction/BottomStateResult.h" #include "storm/abstraction/GameBddResult.h" #include "storm/storage/dd/DdManager.h" #include "storm/storage/dd/Add.h" #include "storm/storage/jani/Automaton.h" #include "storm/settings/SettingsManager.h" #include "storm-config.h" #include "storm/adapters/CarlAdapter.h" #include "storm/utility/macros.h" namespace storm { namespace abstraction { namespace jani { using storm::settings::modules::AbstractionSettings; template <storm::dd::DdType DdType, typename ValueType> AutomatonAbstractor<DdType, ValueType>::AutomatonAbstractor(storm::jani::Automaton const& automaton, AbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> 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; } } template <storm::dd::DdType DdType, typename ValueType> void AutomatonAbstractor<DdType, ValueType>::refine(std::vector<uint_fast64_t> 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::dd::DdType DdType, typename ValueType> storm::expressions::Expression const& AutomatonAbstractor<DdType, ValueType>::getGuard(uint64_t player1Choice) const { return edges[player1Choice].getGuard(); } template <storm::dd::DdType DdType, typename ValueType> std::map<storm::expressions::Variable, storm::expressions::Expression> AutomatonAbstractor<DdType, ValueType>::getVariableUpdates(uint64_t player1Choice, uint64_t auxiliaryChoice) const { return edges[player1Choice].getVariableUpdates(auxiliaryChoice); } template <storm::dd::DdType DdType, typename ValueType> GameBddResult<DdType> AutomatonAbstractor<DdType, ValueType>::abstract() { // First, we retrieve the abstractions of all commands. std::vector<GameBddResult<DdType>> 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<DdType> result = this->getAbstractionInformation().getDdManager().getBddZero(); for (auto const& edgeDd : edgeDdsAndUsedOptionVariableCounts) { result |= edgeDd.bdd && this->getAbstractionInformation().getPlayer2ZeroCube(edgeDd.numberOfPlayer2Variables, maximalNumberOfUsedOptionVariables); } return GameBddResult<DdType>(result, maximalNumberOfUsedOptionVariables); } template <storm::dd::DdType DdType, typename ValueType> BottomStateResult<DdType> AutomatonAbstractor<DdType, ValueType>::getBottomStateTransitions(storm::dd::Bdd<DdType> const& reachableStates, uint_fast64_t numberOfPlayer2Variables) { BottomStateResult<DdType> result(this->getAbstractionInformation().getDdManager().getBddZero(), this->getAbstractionInformation().getDdManager().getBddZero()); for (auto& edge : edges) { BottomStateResult<DdType> commandBottomStateResult = edge.getBottomStateTransitions(reachableStates, numberOfPlayer2Variables); result.states |= commandBottomStateResult.states; result.transitions |= commandBottomStateResult.transitions; } return result; } template <storm::dd::DdType DdType, typename ValueType> storm::dd::Add<DdType, ValueType> AutomatonAbstractor<DdType, ValueType>::getEdgeUpdateProbabilitiesAdd() const { storm::dd::Add<DdType, ValueType> result = this->getAbstractionInformation().getDdManager().template getAddZero<ValueType>(); for (auto const& edge : edges) { result += edge.getEdgeUpdateProbabilitiesAdd(); } return result; } template <storm::dd::DdType DdType, typename ValueType> std::vector<EdgeAbstractor<DdType, ValueType>> const& AutomatonAbstractor<DdType, ValueType>::getEdges() const { return edges; } template <storm::dd::DdType DdType, typename ValueType> std::vector<EdgeAbstractor<DdType, ValueType>>& AutomatonAbstractor<DdType, ValueType>::getEdges() { return edges; } template <storm::dd::DdType DdType, typename ValueType> std::size_t AutomatonAbstractor<DdType, ValueType>::getNumberOfEdges() const { return edges.size(); } template <storm::dd::DdType DdType, typename ValueType> AbstractionInformation<DdType> const& AutomatonAbstractor<DdType, ValueType>::getAbstractionInformation() const { return abstractionInformation.get(); } template class AutomatonAbstractor<storm::dd::DdType::CUDD, double>; template class AutomatonAbstractor<storm::dd::DdType::Sylvan, double>; #ifdef STORM_HAVE_CARL template class AutomatonAbstractor<storm::dd::DdType::Sylvan, storm::RationalFunction>; #endif } } }