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.
195 lines
8.8 KiB
195 lines
8.8 KiB
#include "storm/logic/CumulativeRewardFormula.h"
|
|
|
|
#include "storm/logic/FormulaVisitor.h"
|
|
|
|
#include "storm/utility/macros.h"
|
|
#include "storm/utility/constants.h"
|
|
#include "storm/exceptions/InvalidPropertyException.h"
|
|
#include "storm/exceptions/InvalidOperationException.h"
|
|
|
|
namespace storm {
|
|
namespace logic {
|
|
CumulativeRewardFormula::CumulativeRewardFormula(TimeBound const& bound, TimeBoundReference const& timeBoundReference, boost::optional<RewardAccumulation> rewardAccumulation) : timeBoundReferences({timeBoundReference}), bounds({bound}), rewardAccumulation(rewardAccumulation) {
|
|
// Intentionally left empty.
|
|
}
|
|
|
|
CumulativeRewardFormula::CumulativeRewardFormula(std::vector<TimeBound> const& bounds, std::vector<TimeBoundReference> const& timeBoundReferences, boost::optional<RewardAccumulation> rewardAccumulation) : timeBoundReferences(timeBoundReferences), bounds(bounds), rewardAccumulation(rewardAccumulation) {
|
|
|
|
STORM_LOG_ASSERT(this->timeBoundReferences.size() == this->bounds.size(), "Number of time bounds and number of time bound references does not match.");
|
|
STORM_LOG_ASSERT(!this->timeBoundReferences.empty(), "No time bounds given.");
|
|
}
|
|
|
|
bool CumulativeRewardFormula::isCumulativeRewardFormula() const {
|
|
return true;
|
|
}
|
|
|
|
bool CumulativeRewardFormula::isRewardPathFormula() const {
|
|
return true;
|
|
}
|
|
|
|
bool CumulativeRewardFormula::isMultiDimensional() const {
|
|
return getDimension() > 1;
|
|
}
|
|
|
|
unsigned CumulativeRewardFormula::getDimension() const {
|
|
return timeBoundReferences.size();
|
|
}
|
|
|
|
boost::any CumulativeRewardFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
|
|
return visitor.visit(*this, data);
|
|
}
|
|
|
|
void CumulativeRewardFormula::gatherReferencedRewardModels(std::set<std::string>& referencedRewardModels) const {
|
|
for (unsigned i = 0; i < this->getDimension(); ++i) {
|
|
if (getTimeBoundReference(i).isRewardBound()) {
|
|
referencedRewardModels.insert(this->getTimeBoundReference(i).getRewardName());
|
|
}
|
|
}
|
|
}
|
|
|
|
TimeBoundReference const& CumulativeRewardFormula::getTimeBoundReference() const {
|
|
STORM_LOG_ASSERT(!isMultiDimensional(), "Cumulative Reward Formula is multi-dimensional.");
|
|
return getTimeBoundReference(0);
|
|
}
|
|
|
|
TimeBoundReference const& CumulativeRewardFormula::getTimeBoundReference(unsigned i) const {
|
|
return timeBoundReferences.at(i);
|
|
}
|
|
|
|
bool CumulativeRewardFormula::isBoundStrict() const {
|
|
STORM_LOG_ASSERT(!isMultiDimensional(), "Cumulative Reward Formula is multi-dimensional.");
|
|
return isBoundStrict(0);
|
|
}
|
|
|
|
bool CumulativeRewardFormula::isBoundStrict(unsigned i) const {
|
|
return bounds.at(i).isStrict();
|
|
}
|
|
|
|
bool CumulativeRewardFormula::hasIntegerBound() const {
|
|
STORM_LOG_ASSERT(!isMultiDimensional(), "Cumulative Reward Formula is multi-dimensional.");
|
|
return hasIntegerBound(0);
|
|
}
|
|
|
|
bool CumulativeRewardFormula::hasIntegerBound(unsigned i) const {
|
|
return bounds.at(i).getBound().hasIntegerType();
|
|
}
|
|
|
|
storm::expressions::Expression const& CumulativeRewardFormula::getBound() const {
|
|
STORM_LOG_ASSERT(!isMultiDimensional(), "Cumulative Reward Formula is multi-dimensional.");
|
|
return getBound(0);
|
|
}
|
|
|
|
storm::expressions::Expression const& CumulativeRewardFormula::getBound(unsigned i) const {
|
|
return bounds.at(i).getBound();
|
|
}
|
|
|
|
template <typename ValueType>
|
|
ValueType CumulativeRewardFormula::getBound() const {
|
|
STORM_LOG_ASSERT(!isMultiDimensional(), "Cumulative Reward Formula is multi-dimensional.");
|
|
return getBound<ValueType>(0);
|
|
}
|
|
|
|
template <>
|
|
double CumulativeRewardFormula::getBound(unsigned i) const {
|
|
checkNoVariablesInBound(bounds.at(i).getBound());
|
|
double value = bounds.at(i).getBound().evaluateAsDouble();
|
|
STORM_LOG_THROW(value >= 0.0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
|
|
return value;
|
|
}
|
|
|
|
template <>
|
|
storm::RationalNumber CumulativeRewardFormula::getBound(unsigned i) const {
|
|
checkNoVariablesInBound(bounds.at(i).getBound());
|
|
storm::RationalNumber value = bounds.at(i).getBound().evaluateAsRational();
|
|
STORM_LOG_THROW(value >= storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
|
|
return value;
|
|
}
|
|
|
|
template <>
|
|
uint64_t CumulativeRewardFormula::getBound(unsigned i) const {
|
|
checkNoVariablesInBound(bounds.at(i).getBound());
|
|
uint64_t value = bounds.at(i).getBound().evaluateAsInt();
|
|
STORM_LOG_THROW(value >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
|
|
return value;
|
|
}
|
|
|
|
template <>
|
|
double CumulativeRewardFormula::getNonStrictBound() const {
|
|
STORM_LOG_ASSERT(!isMultiDimensional(), "Cumulative Reward Formula is multi-dimensional.");
|
|
double bound = getBound<double>();
|
|
STORM_LOG_THROW(bound > 0, storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict bound from strict zero-bound.");
|
|
return bound;
|
|
}
|
|
|
|
template <>
|
|
uint64_t CumulativeRewardFormula::getNonStrictBound() const {
|
|
STORM_LOG_ASSERT(!isMultiDimensional(), "Cumulative Reward Formula is multi-dimensional.");
|
|
int_fast64_t bound = getBound<uint64_t>();
|
|
if (isBoundStrict()) {
|
|
STORM_LOG_THROW(bound > 0, storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict bound from strict zero-bound.");
|
|
return bound - 1;
|
|
} else {
|
|
return bound;
|
|
}
|
|
}
|
|
|
|
void CumulativeRewardFormula::checkNoVariablesInBound(storm::expressions::Expression const& bound) {
|
|
STORM_LOG_THROW(!bound.containsVariables(), storm::exceptions::InvalidOperationException, "Cannot evaluate time-bound '" << bound << "' as it contains undefined constants.");
|
|
}
|
|
|
|
bool CumulativeRewardFormula::hasRewardAccumulation() const {
|
|
return rewardAccumulation.is_initialized();
|
|
}
|
|
|
|
RewardAccumulation const& CumulativeRewardFormula::getRewardAccumulation() const {
|
|
return rewardAccumulation.get();
|
|
}
|
|
|
|
|
|
std::shared_ptr<CumulativeRewardFormula const> CumulativeRewardFormula::restrictToDimension(unsigned i) const {
|
|
return std::make_shared<CumulativeRewardFormula const>(bounds.at(i), getTimeBoundReference(i));
|
|
}
|
|
|
|
std::ostream& CumulativeRewardFormula::writeToStream(std::ostream& out) const {
|
|
out << "C";
|
|
if (hasRewardAccumulation()) {
|
|
out << "[" << getRewardAccumulation() << "]";
|
|
}
|
|
if (this->isMultiDimensional()) {
|
|
out << "^{";
|
|
}
|
|
for (unsigned i = 0; i < this->getDimension(); ++i) {
|
|
if (i > 0) {
|
|
out << ", ";
|
|
}
|
|
if (this->getTimeBoundReference(i).isRewardBound()) {
|
|
out << "rew";
|
|
if (this->getTimeBoundReference(i).hasRewardAccumulation()) {
|
|
out << "[" << this->getTimeBoundReference(i).getRewardAccumulation() << "]";
|
|
}
|
|
out << "{\"" << this->getTimeBoundReference(i).getRewardName() << "\"}";
|
|
} else if (this->getTimeBoundReference(i).isStepBound()) {
|
|
out << "steps";
|
|
//} else if (this->getTimeBoundReference(i).isStepBound())
|
|
// Note: the 'time' keyword is optional.
|
|
// out << "time";
|
|
}
|
|
if (this->isBoundStrict(i)) {
|
|
out << "<";
|
|
} else {
|
|
out << "<=";
|
|
}
|
|
out << this->getBound(i);
|
|
}
|
|
if (this->isMultiDimensional()) {
|
|
out << "}";
|
|
}
|
|
return out;
|
|
}
|
|
|
|
template uint64_t CumulativeRewardFormula::getBound<uint64_t>() const;
|
|
template double CumulativeRewardFormula::getBound<double>() const;
|
|
template storm::RationalNumber CumulativeRewardFormula::getBound<storm::RationalNumber>() const;
|
|
|
|
}
|
|
}
|