Tim Quatmann
5 years ago
3 changed files with 444 additions and 280 deletions
-
478src/storm-pomdp-cli/storm-pomdp.cpp
-
177src/storm-pomdp/analysis/FormulaInformation.cpp
-
69src/storm-pomdp/analysis/FormulaInformation.h
@ -0,0 +1,177 @@ |
|||
#include "storm-pomdp/analysis/FormulaInformation.h"
|
|||
#include "storm/logic/Formulas.h"
|
|||
#include "storm/logic/FragmentSpecification.h"
|
|||
#include "storm/models/sparse/Pomdp.h"
|
|||
#include "storm/models/sparse/StandardRewardModel.h"
|
|||
#include "storm/modelchecker/propositional/SparsePropositionalModelChecker.h"
|
|||
#include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h"
|
|||
|
|||
#include "storm/utility/macros.h"
|
|||
#include "storm/exceptions/InvalidPropertyException.h"
|
|||
|
|||
namespace storm { |
|||
namespace pomdp { |
|||
namespace analysis { |
|||
|
|||
bool FormulaInformation::StateSet::empty() const { |
|||
STORM_LOG_ASSERT(states.empty() == observations.empty(), "Inconsistent StateSet."); |
|||
return observations.empty(); |
|||
} |
|||
|
|||
FormulaInformation::FormulaInformation() : type(Type::Unsupported) { |
|||
// Intentionally left empty
|
|||
} |
|||
|
|||
FormulaInformation::FormulaInformation(Type const& type, storm::solver::OptimizationDirection const& dir, boost::optional<std::string> const& rewardModelName) : type(type), optimizationDirection(dir), rewardModelName(rewardModelName) { |
|||
STORM_LOG_ASSERT(!this->rewardModelName.is_initialized() || this->type == Type::NonNestedExpectedRewardFormula, "Got a reward model name for a non-reward formula."); |
|||
|
|||
} |
|||
|
|||
FormulaInformation::Type const& FormulaInformation::getType() const { |
|||
return type; |
|||
} |
|||
|
|||
bool FormulaInformation::isNonNestedReachabilityProbability() const { |
|||
return type == Type::NonNestedReachabilityProbability; |
|||
} |
|||
|
|||
bool FormulaInformation::isNonNestedExpectedRewardFormula() const { |
|||
return type == Type::NonNestedExpectedRewardFormula; |
|||
} |
|||
|
|||
bool FormulaInformation::isUnsupported() const { |
|||
return type == Type::Unsupported; |
|||
} |
|||
|
|||
typename FormulaInformation::StateSet const& FormulaInformation::getTargetStates() const { |
|||
STORM_LOG_ASSERT(this->type == Type::NonNestedExpectedRewardFormula || this->type == Type::NonNestedReachabilityProbability, "Target states requested for unexpected formula type."); |
|||
return targetStates.get(); |
|||
} |
|||
|
|||
typename FormulaInformation::StateSet const& FormulaInformation::getSinkStates() const { |
|||
STORM_LOG_ASSERT(this->type == Type::NonNestedReachabilityProbability, "Sink states requested for unexpected formula type."); |
|||
return sinkStates.get(); |
|||
} |
|||
|
|||
std::string const& FormulaInformation::getRewardModelName() const { |
|||
STORM_LOG_ASSERT(this->type == Type::NonNestedExpectedRewardFormula, "Reward model requested for unexpected formula type."); |
|||
return rewardModelName.get(); |
|||
} |
|||
|
|||
storm::solver::OptimizationDirection const& FormulaInformation::getOptimizationDirection() const { |
|||
return optimizationDirection; |
|||
} |
|||
|
|||
bool FormulaInformation::minimize() const { |
|||
return storm::solver::minimize(optimizationDirection); |
|||
} |
|||
|
|||
bool FormulaInformation::maximize() const { |
|||
return storm::solver::maximize(optimizationDirection); |
|||
} |
|||
|
|||
template <typename PomdpType> |
|||
FormulaInformation::StateSet getStateSet(PomdpType const& pomdp, storm::storage::BitVector&& inputStates) { |
|||
FormulaInformation::StateSet result; |
|||
result.states = std::move(inputStates); |
|||
for (auto const& state : result.states) { |
|||
result.observations.insert(pomdp.getObservation(state)); |
|||
} |
|||
// check if this set is observation-closed, i.e., whether there is a state outside of this set with one of the observations collected above
|
|||
result.observationClosed = true; |
|||
for (uint64_t state = result.states.getNextUnsetIndex(0); state < result.states.size(); state = result.states.getNextUnsetIndex(state + 1)) { |
|||
if (result.observations.count(pomdp.getObservation(state)) > 0) { |
|||
result.observationClosed = false; |
|||
break; |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
template <typename PomdpType> |
|||
void FormulaInformation::updateTargetStates(PomdpType const& pomdp, storm::storage::BitVector&& newTargetStates) { |
|||
STORM_LOG_ASSERT(this->type == Type::NonNestedExpectedRewardFormula || this->type == Type::NonNestedReachabilityProbability, "Target states updated for unexpected formula type."); |
|||
targetStates = getStateSet(pomdp, std::move(newTargetStates)); |
|||
} |
|||
|
|||
template <typename PomdpType> |
|||
void FormulaInformation::updateSinkStates(PomdpType const& pomdp, storm::storage::BitVector&& newSinkStates) { |
|||
STORM_LOG_ASSERT(this->type == Type::NonNestedReachabilityProbability, "Sink states requested for unexpected formula type."); |
|||
sinkStates = getStateSet(pomdp, std::move(newSinkStates)); |
|||
} |
|||
|
|||
template <typename PomdpType> |
|||
storm::storage::BitVector getStates(storm::logic::Formula const& propositionalFormula, bool formulaInverted, PomdpType const& pomdp) { |
|||
storm::modelchecker::SparsePropositionalModelChecker<PomdpType> mc(pomdp); |
|||
auto checkResult = mc.check(propositionalFormula); |
|||
storm::storage::BitVector resultBitVector(checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); |
|||
if (formulaInverted) { |
|||
resultBitVector.complement(); |
|||
} |
|||
return resultBitVector; |
|||
} |
|||
|
|||
template <typename PomdpType> |
|||
FormulaInformation getFormulaInformation(PomdpType const& pomdp, storm::logic::ProbabilityOperatorFormula const& formula) { |
|||
STORM_LOG_THROW(formula.hasOptimalityType(), storm::exceptions::InvalidPropertyException, "The property does not specify an optimization direction (min/max)"); |
|||
STORM_LOG_WARN_COND(!formula.hasBound(), "The probability threshold for the given property will be ignored."); |
|||
auto const& subformula = formula.getSubformula(); |
|||
std::shared_ptr<storm::logic::Formula const> targetStatesFormula, constraintsStatesFormula; |
|||
if (subformula.isEventuallyFormula()) { |
|||
targetStatesFormula = subformula.asEventuallyFormula().getSubformula().asSharedPointer(); |
|||
constraintsStatesFormula = storm::logic::Formula::getTrueFormula()->asSharedPointer(); |
|||
} else if (subformula.isUntilFormula()) { |
|||
storm::logic::UntilFormula const &untilFormula = subformula.asUntilFormula(); |
|||
targetStatesFormula = untilFormula.getRightSubformula().asSharedPointer(); |
|||
constraintsStatesFormula = untilFormula.getLeftSubformula().asSharedPointer(); |
|||
} |
|||
if (targetStatesFormula && targetStatesFormula->isInFragment(storm::logic::propositional()) && constraintsStatesFormula && constraintsStatesFormula->isInFragment(storm::logic::propositional())) { |
|||
FormulaInformation result(FormulaInformation::Type::NonNestedReachabilityProbability, formula.getOptimalityType()); |
|||
result.updateTargetStates(pomdp, getStates(*targetStatesFormula, false, pomdp)); |
|||
result.updateSinkStates(pomdp, getStates(*constraintsStatesFormula, true, pomdp)); |
|||
return result; |
|||
} |
|||
return FormulaInformation(); |
|||
} |
|||
|
|||
template <typename PomdpType> |
|||
FormulaInformation getFormulaInformation(PomdpType const& pomdp, storm::logic::RewardOperatorFormula const& formula) { |
|||
STORM_LOG_THROW(formula.hasOptimalityType(), storm::exceptions::InvalidPropertyException, "The property does not specify an optimization direction (min/max)"); |
|||
STORM_LOG_WARN_COND(formula.hasBound(), "The reward threshold for the given property will be ignored."); |
|||
std::string rewardModelName = ""; |
|||
if (formula.hasRewardModelName()) { |
|||
rewardModelName = formula.getRewardModelName(); |
|||
STORM_LOG_THROW(pomdp.hasRewardModel(rewardModelName), storm::exceptions::InvalidPropertyException, "Selected reward model with name '" << rewardModelName << "' does not exist."); |
|||
} else { |
|||
STORM_LOG_THROW(pomdp.hasUniqueRewardModel(), storm::exceptions::InvalidPropertyException, "Reward operator formula does not specify a reward model and the reward model is not unique."); |
|||
rewardModelName = pomdp.getUniqueRewardModelName(); |
|||
} |
|||
auto const& subformula = formula.getSubformula(); |
|||
std::shared_ptr<storm::logic::Formula const> targetStatesFormula; |
|||
if (subformula.isEventuallyFormula()) { |
|||
targetStatesFormula = subformula.asEventuallyFormula().getSubformula().asSharedPointer(); |
|||
} |
|||
if (targetStatesFormula && targetStatesFormula->isInFragment(storm::logic::propositional())) { |
|||
FormulaInformation result(FormulaInformation::Type::NonNestedReachabilityProbability, formula.getOptimalityType(), rewardModelName); |
|||
result.updateTargetStates(pomdp, getStates(*targetStatesFormula, false, pomdp)); |
|||
return result; |
|||
} |
|||
return FormulaInformation(); |
|||
} |
|||
|
|||
template <typename PomdpType> |
|||
FormulaInformation getFormulaInformation(PomdpType const& pomdp, storm::logic::Formula const& formula) { |
|||
if (formula.isProbabilityOperatorFormula()) { |
|||
return getFormulaInformation(pomdp, formula.asProbabilityOperatorFormula()); |
|||
} else if (formula.isRewardOperatorFormula()) { |
|||
return getFormulaInformation(pomdp, formula.asRewardOperatorFormula()); |
|||
} |
|||
return FormulaInformation(); |
|||
} |
|||
|
|||
template FormulaInformation getFormulaInformation<storm::models::sparse::Pomdp<double>>(storm::models::sparse::Pomdp<double> const& pomdp, storm::logic::Formula const& formula); |
|||
template FormulaInformation getFormulaInformation<storm::models::sparse::Pomdp<storm::RationalNumber>>(storm::models::sparse::Pomdp<storm::RationalNumber> const& pomdp, storm::logic::Formula const& formula); |
|||
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,69 @@ |
|||
#pragma once |
|||
|
|||
#include <set> |
|||
#include <string> |
|||
#include <boost/optional.hpp> |
|||
|
|||
#include "storm/storage/BitVector.h" |
|||
#include "storm/solver/OptimizationDirection.h" |
|||
|
|||
namespace storm { |
|||
|
|||
namespace logic { |
|||
class Formula; |
|||
} |
|||
|
|||
namespace pomdp { |
|||
namespace analysis { |
|||
class FormulaInformation { |
|||
public: |
|||
/// Characterizes a certain set of states |
|||
struct StateSet { |
|||
storm::storage::BitVector states; // The set of states |
|||
std::set<uint32_t> observations; // The set of the observations that are assigned to at least one state of the set |
|||
bool observationClosed; // True iff this state set can be uniquely characterized by the observations |
|||
bool empty() const; |
|||
}; |
|||
|
|||
/// Possible supported formula types |
|||
enum class Type { |
|||
NonNestedReachabilityProbability, // e.g. 'Pmax=? [F "target"]' or 'Pmin=? [!"sink" U "target"]' |
|||
NonNestedExpectedRewardFormula, // e.g. 'Rmin=? [F x>0 ]' |
|||
Unsupported // The formula type is unsupported |
|||
}; |
|||
|
|||
FormulaInformation(); // Unsupported |
|||
FormulaInformation(Type const& type, storm::solver::OptimizationDirection const& dir, boost::optional<std::string> const& rewardModelName = boost::none); |
|||
|
|||
Type const& getType() const; |
|||
bool isNonNestedReachabilityProbability() const; |
|||
bool isNonNestedExpectedRewardFormula() const; |
|||
bool isUnsupported() const; |
|||
StateSet const& getTargetStates() const; |
|||
StateSet const& getSinkStates() const; // Shall not be called for reward formulas |
|||
std::string const& getRewardModelName() const; // Shall not be called for probability formulas |
|||
storm::solver::OptimizationDirection const& getOptimizationDirection() const; |
|||
bool minimize() const; |
|||
bool maximize() const; |
|||
|
|||
template <typename PomdpType> |
|||
void updateTargetStates(PomdpType const& pomdp, storm::storage::BitVector&& newTargetStates); |
|||
|
|||
template <typename PomdpType> |
|||
void updateSinkStates(PomdpType const& pomdp, storm::storage::BitVector&& newSinkStates); |
|||
|
|||
private: |
|||
Type type; |
|||
storm::solver::OptimizationDirection optimizationDirection; |
|||
boost::optional<StateSet> targetStates; |
|||
boost::optional<StateSet> sinkStates; |
|||
boost::optional<std::string> rewardModelName; |
|||
}; |
|||
|
|||
template <typename PomdpType> |
|||
FormulaInformation getFormulaInformation(PomdpType const& pomdp, storm::logic::Formula const& formula); |
|||
|
|||
|
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue