You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
9.3 KiB
148 lines
9.3 KiB
#ifndef STORM_UTILITY_PARAMETERLIFTING_H
|
|
#define STORM_UTILITY_PARAMETERLIFTING_H
|
|
|
|
#include <vector>
|
|
|
|
#include "storm-pars/utility/parametric.h"
|
|
#include "storm/models/sparse/Model.h"
|
|
#include "storm/utility/macros.h"
|
|
#include "storm/logic/Formula.h"
|
|
#include "storm/logic/FragmentSpecification.h"
|
|
#include "storm/models/sparse/MarkovAutomaton.h"
|
|
#include "storm/models/sparse/StandardRewardModel.h"
|
|
|
|
|
|
namespace storm {
|
|
namespace utility {
|
|
namespace parameterlifting {
|
|
|
|
/*!
|
|
* Checks whether the parameter lifting approach is sound on the given model with respect to the provided property
|
|
*
|
|
* This method is taylored to an efficient but incomplete check, i.e., if false is returned,
|
|
* parameter lifting might still be applicable.
|
|
*
|
|
* More precisely, we only check if the occurring functions are multilinear polynomials.
|
|
* However, Parameter Lifting also works for fractions of multilinear polynomials where for every state s,
|
|
* every probability and reward occurring at s have the same denominator.
|
|
*
|
|
* @param model
|
|
* @param formula
|
|
* @return true iff it was successfully validated that parameter lifting is sound on the provided model.
|
|
*/
|
|
template<typename ValueType>
|
|
static bool validateParameterLiftingSound(storm::models::sparse::Model<ValueType> const& model, storm::logic::Formula const& formula) {
|
|
|
|
// Check whether all numbers occurring in the model are multilinear
|
|
|
|
// Transition matrix
|
|
if (model.isOfType(storm::models::ModelType::Dtmc) || model.isOfType(storm::models::ModelType::Mdp) || model.isOfType(storm::models::ModelType::Ctmc)) {
|
|
for (auto const& entry : model.getTransitionMatrix()) {
|
|
if (!storm::utility::parametric::isMultiLinearPolynomial(entry.getValue())) {
|
|
STORM_LOG_WARN("The input model contains a non-linear polynomial as transition: '" << entry.getValue() << "'. Can not validate that parameter lifting is sound on this model.");
|
|
return false;
|
|
}
|
|
}
|
|
} else if (model.isOfType(storm::models::ModelType::MarkovAutomaton)) {
|
|
auto const& ma = dynamic_cast<storm::models::sparse::MarkovAutomaton<ValueType> const&>(model);
|
|
// Markov Automata store the probability matrix and the exit rate vector. However, we need to considert the rate matrix.
|
|
if (!ma.isClosed()) {
|
|
STORM_LOG_ERROR("parameter lifting requires a closed Markov automaton.");
|
|
return false;
|
|
}
|
|
auto const& rateVector = ma.getExitRates();
|
|
auto const& markovianStates = ma.getMarkovianStates();
|
|
for (uint_fast64_t state = 0; state < model.getNumberOfStates(); ++state) {
|
|
if (markovianStates.get(state)) {
|
|
auto const& exitRate = rateVector[state];
|
|
for (auto const& entry : model.getTransitionMatrix().getRowGroup(state)) {
|
|
if (!storm::utility::parametric::isMultiLinearPolynomial(storm::utility::simplify(entry.getValue() * exitRate))) {
|
|
STORM_LOG_WARN("The input model contains a non-linear polynomial as transition rate: '" << storm::utility::simplify(entry.getValue() * exitRate) << "'. Can not validate that parameter lifting is sound on this model.");
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
for (auto const& entry : model.getTransitionMatrix().getRowGroup(state)) {
|
|
if (!storm::utility::parametric::isMultiLinearPolynomial(entry.getValue())) {
|
|
STORM_LOG_WARN("The input model contains a non-linear polynomial as transition: '" << entry.getValue() << "'. Can not validate that parameter lifting is sound on this model.");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
STORM_LOG_ERROR("Unsupported model type for parameter lifting.");
|
|
return false;
|
|
}
|
|
|
|
// Rewards
|
|
if (formula.isRewardOperatorFormula()) {
|
|
storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel = formula.asRewardOperatorFormula().hasRewardModelName() ?
|
|
model.getRewardModel(formula.asRewardOperatorFormula().getRewardModelName()) :
|
|
model.getUniqueRewardModel();
|
|
if (rewardModel.hasStateRewards()) {
|
|
for (auto const& rew : rewardModel.getStateRewardVector()) {
|
|
if (!storm::utility::parametric::isMultiLinearPolynomial(rew)) {
|
|
STORM_LOG_WARN("The input model contains a non-linear polynomial as state reward: '" << rew << "'. Can not validate that parameter lifting is sound on this model.");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
// Parameters in transition rewards (and for continuous time models also action rewards) have to be disjoint from the probability/rate parameters.
|
|
// Note: This check could also be done action-wise.
|
|
std::set<typename storm::utility::parametric::VariableType<ValueType>::type> collectedRewardParameters;
|
|
if (rewardModel.hasStateActionRewards()) {
|
|
if (model.isOfType(storm::models::ModelType::Ctmc) || model.isOfType(storm::models::ModelType::MarkovAutomaton)) {
|
|
for (auto const& rew : rewardModel.getStateActionRewardVector()) {
|
|
if (!storm::utility::parametric::isMultiLinearPolynomial(rew)) {
|
|
STORM_LOG_WARN("The input model contains a non-linear polynomial as action reward: '" << rew << "'. Can not validate that parameter lifting is sound on this model.");
|
|
return false;
|
|
}
|
|
storm::utility::parametric::gatherOccurringVariables(rew, collectedRewardParameters);
|
|
}
|
|
} else {
|
|
for (auto const& rew : rewardModel.getStateActionRewardVector()) {
|
|
if (!storm::utility::parametric::isMultiLinearPolynomial(rew)) {
|
|
STORM_LOG_WARN("The input model contains a non-linear polynomial as action reward: '" << rew << "'. Can not validate that parameter lifting is sound on this model.");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rewardModel.hasTransitionRewards()) {
|
|
for (auto const& rewEntry : rewardModel.getTransitionRewardMatrix()) {
|
|
if (!storm::utility::parametric::isMultiLinearPolynomial(rewEntry.getValue())) {
|
|
STORM_LOG_WARN("The input model contains a non-linear polynomial as transition reward: '" << rewEntry.getValue() << "'. Can not validate that parameter lifting is sound on this model.");
|
|
return false;
|
|
}
|
|
storm::utility::parametric::gatherOccurringVariables(rewEntry.getValue(), collectedRewardParameters);
|
|
}
|
|
}
|
|
|
|
if (!collectedRewardParameters.empty()) {
|
|
std::set<typename storm::utility::parametric::VariableType<ValueType>::type> transitionParameters = storm::models::sparse::getProbabilityParameters(model);
|
|
auto rewParIt = collectedRewardParameters.begin();
|
|
auto trParIt = transitionParameters.begin();
|
|
while (rewParIt != collectedRewardParameters.end() && trParIt != transitionParameters.end()) {
|
|
if (*rewParIt == *trParIt) {
|
|
STORM_LOG_WARN("Parameter " << *trParIt << " occurs in a transition probability/rate and in a transition/action reward. Parameter lifting might not be sound on this model.");
|
|
return false;
|
|
}
|
|
if (*rewParIt < *trParIt) {
|
|
++rewParIt;
|
|
} else {
|
|
++trParIt;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* STORM_UTILITY_PARAMETERLIFTING_H */
|