Browse Source
Started to restructure LTL model checking algorithms
Started to restructure LTL model checking algorithms
Conflicts: src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpptempestpy_adaptions
hannah
4 years ago
committed by
Stefan Pranger
8 changed files with 291 additions and 32 deletions
-
10src/storm/modelchecker/helper/SingleValueModelCheckerHelper.cpp
-
11src/storm/modelchecker/helper/SingleValueModelCheckerHelper.h
-
192src/storm/modelchecker/helper/ltl/SparseLTLHelper.cpp
-
52src/storm/modelchecker/helper/ltl/SparseLTLHelper.h
-
7src/storm/modelchecker/helper/utility/SetInformationFromCheckTask.h
-
28src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp
-
21src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp
-
2src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h
@ -0,0 +1,192 @@ |
|||
#include "SparseLTLHelper.h"
|
|||
|
|||
#include "storm/transformer/DAProductBuilder.h"
|
|||
#include "storm/automata/LTL2DeterministicAutomaton.h"
|
|||
|
|||
#include "storm/models/sparse/Dtmc.h"
|
|||
#include "storm/models/sparse/Mdp.h"
|
|||
|
|||
#include "storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h"
|
|||
#include "storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h"
|
|||
|
|||
#include "storm/storage/StronglyConnectedComponentDecomposition.h"
|
|||
|
|||
#include "storm/settings/SettingsManager.h"
|
|||
#include "storm/settings/modules/DebugSettings.h"
|
|||
#include "storm/exceptions/InvalidPropertyException.h"
|
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
template <typename ValueType, typename Model, bool Nondeterministic> |
|||
SparseLTLHelper<ValueType, Model, Nondeterministic>::SparseLTLHelper(Model const& model, storm::storage::SparseMatrix<ValueType> const& transitionMatrix) : _model(model), _transitionMatrix(transitionMatrix) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType, typename Model, bool Nondeterministic> |
|||
std::vector<ValueType> SparseLTLHelper<ValueType, Model, Nondeterministic>::computeDAProductProbabilities(Environment const& env, storm::solver::SolveGoal<ValueType>&& goal, storm::automata::DeterministicAutomaton const& da, std::map<std::string, storm::storage::BitVector>& apSatSets, bool qualitative) { |
|||
STORM_LOG_THROW((!Nondeterministic) || goal.hasDirection() && goal.direction() == OptimizationDirection::Maximize, storm::exceptions::InvalidPropertyException, "Can only compute maximizing probabilties for DA product with MDP"); |
|||
|
|||
|
|||
const storm::automata::APSet& apSet = da.getAPSet(); |
|||
|
|||
std::vector<storm::storage::BitVector> apLabels; |
|||
for (const std::string& ap : apSet.getAPs()) { |
|||
auto it = apSatSets.find(ap); |
|||
STORM_LOG_THROW(it != apSatSets.end(), storm::exceptions::InvalidOperationException, "Deterministic automaton has AP " << ap << ", does not appear in formula"); |
|||
|
|||
apLabels.push_back(std::move(it->second)); |
|||
} |
|||
|
|||
storm::storage::BitVector statesOfInterest; |
|||
if (goal.hasRelevantValues()) { |
|||
statesOfInterest = goal.relevantValues(); |
|||
} else { |
|||
// product from all model states
|
|||
statesOfInterest = storm::storage::BitVector(this->_model.getNumberOfStates(), true); |
|||
} |
|||
|
|||
|
|||
STORM_LOG_INFO("Building "+ (Nondeterministic ? std::string("MDP-DA") : std::string("DTMC-DA")) +"product with deterministic automaton, starting from " << statesOfInterest.getNumberOfSetBits() << " model states..."); |
|||
storm::transformer::DAProductBuilder productBuilder(da, apLabels); |
|||
|
|||
auto product = productBuilder.build(this->_model, statesOfInterest); |
|||
|
|||
STORM_LOG_INFO("Product "+ (Nondeterministic ? std::string("MDP-DA") : std::string("DTMC")) +" has " << product->getProductModel().getNumberOfStates() << " states and " |
|||
<< product->getProductModel().getNumberOfTransitions() << " transitions."); |
|||
|
|||
if (storm::settings::getModule<storm::settings::modules::DebugSettings>().isTraceSet()) { |
|||
STORM_LOG_TRACE("Writing model to model.dot"); |
|||
std::ofstream modelDot("model.dot"); |
|||
this->_model.writeDotToStream(modelDot); |
|||
modelDot.close(); |
|||
|
|||
STORM_LOG_TRACE("Writing product model to product.dot"); |
|||
std::ofstream productDot("product.dot"); |
|||
product->getProductModel().writeDotToStream(productDot); |
|||
productDot.close(); |
|||
|
|||
STORM_LOG_TRACE("Product model mapping:"); |
|||
std::stringstream str; |
|||
product->printMapping(str); |
|||
STORM_LOG_TRACE(str.str()); |
|||
} |
|||
|
|||
|
|||
// DTMC: BCC
|
|||
// MDP: computeSurelyAcceptingPmaxStates
|
|||
storm::storage::BitVector accepting; |
|||
if (Nondeterministic) { |
|||
STORM_LOG_INFO("Computing accepting end components..."); |
|||
accepting = storm::modelchecker::helper::SparseMdpPrctlHelper<ValueType>::computeSurelyAcceptingPmaxStates(*product->getAcceptance(), product->getProductModel().getTransitionMatrix(), product->getProductModel().getBackwardTransitions()); |
|||
if (accepting.empty()) { |
|||
STORM_LOG_INFO("No accepting states, skipping probability computation."); |
|||
std::vector<ValueType> numericResult(this->_model.getNumberOfStates(), storm::utility::zero<ValueType>()); |
|||
return numericResult; |
|||
} |
|||
|
|||
} else { |
|||
STORM_LOG_INFO("Computing BSCCs and checking for acceptance..."); |
|||
|
|||
storm::storage::StronglyConnectedComponentDecomposition<ValueType> bottomSccs(product->getProductModel().getTransitionMatrix(), |
|||
storage::StronglyConnectedComponentDecompositionOptions().onlyBottomSccs().dropNaiveSccs()); |
|||
accepting = storm::storage::BitVector(product->getProductModel().getNumberOfStates()); |
|||
std::size_t checkedBSCCs = 0, acceptingBSCCs = 0, acceptingBSCCStates = 0; |
|||
for (auto& scc : bottomSccs) { |
|||
checkedBSCCs++; |
|||
if (product->getAcceptance()->isAccepting(scc)) { |
|||
acceptingBSCCs++; |
|||
for (auto& state : scc) { |
|||
accepting.set(state); |
|||
acceptingBSCCStates++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
STORM_LOG_INFO("BSCC analysis: " << acceptingBSCCs << " of " << checkedBSCCs << " BSCCs were accepting (" << acceptingBSCCStates << " states in accepting BSCCs)."); |
|||
|
|||
if (acceptingBSCCs == 0) { |
|||
STORM_LOG_INFO("No accepting BSCCs, skipping probability computation."); |
|||
std::vector<ValueType> numericResult(this->_model.getNumberOfStates(), storm::utility::zero<ValueType>()); |
|||
return numericResult; |
|||
} |
|||
} |
|||
|
|||
STORM_LOG_INFO("Computing probabilities for reaching accepting BSCCs..."); |
|||
|
|||
storm::storage::BitVector bvTrue(product->getProductModel().getNumberOfStates(), true); |
|||
|
|||
storm::solver::SolveGoal<ValueType> solveGoalProduct(goal); |
|||
storm::storage::BitVector soiProduct(product->getStatesOfInterest()); |
|||
solveGoalProduct.setRelevantValues(std::move(soiProduct)); |
|||
|
|||
std::vector<ValueType> prodNumericResult; |
|||
|
|||
if (Nondeterministic) { |
|||
prodNumericResult |
|||
= std::move(storm::modelchecker::helper::SparseMdpPrctlHelper<ValueType>::computeUntilProbabilities(env, |
|||
std::move(solveGoalProduct), |
|||
product->getProductModel().getTransitionMatrix(), |
|||
product->getProductModel().getBackwardTransitions(), |
|||
bvTrue, |
|||
accepting, |
|||
qualitative, |
|||
false // no schedulers (at the moment)
|
|||
).values); |
|||
|
|||
} else { |
|||
prodNumericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper<ValueType>::computeUntilProbabilities(env, |
|||
std::move(solveGoalProduct), |
|||
product->getProductModel().getTransitionMatrix(), |
|||
product->getProductModel().getBackwardTransitions(), |
|||
bvTrue, |
|||
accepting, |
|||
qualitative); |
|||
} |
|||
|
|||
std::vector<ValueType> numericResult = product->projectToOriginalModel(this->_model, prodNumericResult); |
|||
return numericResult; |
|||
} |
|||
|
|||
|
|||
template<typename ValueType, typename RewardModelType, bool Nondeterministic> |
|||
std::vector <ValueType> SparseLTLHelper<ValueType, RewardModelType, Nondeterministic>::computeLTLProbabilities(Environment const &env, storm::solver::SolveGoal<ValueType>&& goal, storm::logic::Formula const& ltlFormula, std::map<std::string, storm::storage::BitVector>& apSatSets) { |
|||
STORM_LOG_INFO("Resulting LTL path formula: " << ltlFormula); |
|||
STORM_LOG_INFO(" in prefix format: " << ltlFormula.toPrefixString()); |
|||
|
|||
std::shared_ptr<storm::automata::DeterministicAutomaton> da = storm::automata::LTL2DeterministicAutomaton::ltl2da(ltlFormula); |
|||
|
|||
STORM_LOG_INFO("Deterministic automaton for LTL formula has " |
|||
<< da->getNumberOfStates() << " states, " |
|||
<< da->getAPSet().size() << " atomic propositions and " |
|||
<< *da->getAcceptance()->getAcceptanceExpression() << " as acceptance condition."); |
|||
|
|||
|
|||
std::vector<ValueType> numericResult = computeDAProductProbabilities(env, std::move(goal), *da, apSatSets, this->isQualitativeSet()); |
|||
|
|||
/*
|
|||
if(Nondeterministic && this->getOptimizationDirection()==OptimizationDirection::Minimize) { |
|||
// compute 1-Pmax[!ltl]
|
|||
for (auto& value : numericResult) { |
|||
value = storm::utility::one<ValueType>() - value; |
|||
} |
|||
} |
|||
*/ |
|||
|
|||
return numericResult; |
|||
} |
|||
|
|||
template class SparseLTLHelper<double, storm::models::sparse::Dtmc<double>, false>; |
|||
template class SparseLTLHelper<double, storm::models::sparse::Mdp<double>, true>; |
|||
|
|||
#ifdef STORM_HAVE_CARL
|
|||
template class SparseLTLHelper<storm::RationalNumber, storm::models::sparse::Dtmc<storm::RationalNumber>, false>; |
|||
template class SparseLTLHelper<storm::RationalNumber, storm::models::sparse::Mdp<storm::RationalNumber>, true>; |
|||
template class SparseLTLHelper<storm::RationalFunction, storm::models::sparse::Dtmc<storm::RationalFunction>, false>; |
|||
|
|||
#endif
|
|||
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,52 @@ |
|||
#include "storm/modelchecker/helper/SingleValueModelCheckerHelper.h" |
|||
#include "storm/storage/SparseMatrix.h" |
|||
#include "storm/solver/SolveGoal.h" |
|||
|
|||
|
|||
namespace storm { |
|||
|
|||
namespace automata { |
|||
// fwd |
|||
class DeterministicAutomaton; |
|||
} |
|||
|
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
/*! |
|||
* Helper class for todo... |
|||
* @tparam ValueType the type a value can have |
|||
* @tparam Nondeterministic true if there is nondeterminism in the Model (MDP) |
|||
*/ |
|||
template<typename ValueType, typename Model, bool Nondeterministic> // todo remove Model |
|||
class SparseLTLHelper: public SingleValueModelCheckerHelper<ValueType, storm::models::ModelRepresentation::Sparse> { |
|||
|
|||
public: |
|||
/*! |
|||
* Initializes the helper for a discrete time (i.e. DTMC, MDP) |
|||
*/ |
|||
SparseLTLHelper(Model const& model, storm::storage::SparseMatrix<ValueType> const& transitionMatrix); |
|||
|
|||
|
|||
/*! |
|||
* todo |
|||
* @return |
|||
*/ |
|||
std::vector<ValueType> computeDAProductProbabilities(Environment const& env, storm::solver::SolveGoal<ValueType>&& goal, storm::automata::DeterministicAutomaton const& da, std::map<std::string, storm::storage::BitVector>& apSatSets, bool qualitative); |
|||
|
|||
|
|||
/*! |
|||
* Computes the ltl probabilities ...todo |
|||
* @return a value for each state |
|||
*/ |
|||
std::vector<ValueType> computeLTLProbabilities(Environment const &env, storm::solver::SolveGoal<ValueType>&& goal, storm::logic::Formula const& f, std::map<std::string, storm::storage::BitVector>& apSatSets); //todo was brauchen wir hier aps und ..? |
|||
|
|||
|
|||
private: |
|||
storm::storage::SparseMatrix<ValueType> const& _transitionMatrix; |
|||
Model const& _model; // todo remove ? |
|||
|
|||
}; |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue