/* * Ctmdp.h * * Created on: 14.01.2013 * Author: Philipp Berger */ #ifndef STORM_MODELS_CTMDP_H_ #define STORM_MODELS_CTMDP_H_ #include #include #include "AtomicPropositionsLabeling.h" #include "AbstractNondeterministicModel.h" #include "src/storage/SparseMatrix.h" #include "src/settings/Settings.h" namespace storm { namespace models { /*! * This class represents a Markov Decision Process (CTMDP) whose states are * labeled with atomic propositions. */ template class Ctmdp : public storm::models::AbstractNondeterministicModel { public: /*! * Constructs a CTMDP object from the given transition probability matrix and * the given labeling of the states. * All values are copied. * @param probabilityMatrix The transition probability relation of the * CTMDP given by a matrix. * @param stateLabeling The labeling that assigns a set of atomic * propositions to each state. */ Ctmdp(storm::storage::SparseMatrix const& probabilityMatrix, storm::models::AtomicPropositionsLabeling const& stateLabeling, std::vector const& nondeterministicChoiceIndices, boost::optional> const& optionalStateRewardVector, boost::optional> const& optionalTransitionRewardMatrix, boost::optional>> const& optionalChoiceLabeling) : AbstractNondeterministicModel(probabilityMatrix, stateLabeling, nondeterministicChoiceIndices, optionalStateRewardVector, optionalTransitionRewardMatrix, optionalChoiceLabeling) { if (!this->checkValidityOfProbabilityMatrix()) { LOG4CPLUS_ERROR(logger, "Probability matrix is invalid."); throw storm::exceptions::InvalidArgumentException() << "Probability matrix is invalid."; } } /*! * Constructs a CTMDP object from the given transition probability matrix and * the given labeling of the states. * All values are moved. * @param probabilityMatrix The transition probability relation of the * CTMDP given by a matrix. * @param stateLabeling The labeling that assigns a set of atomic * propositions to each state. */ Ctmdp(storm::storage::SparseMatrix&& probabilityMatrix, storm::models::AtomicPropositionsLabeling&& stateLabeling, std::vector&& nondeterministicChoiceIndices, boost::optional>&& optionalStateRewardVector, boost::optional>&& optionalTransitionRewardMatrix, boost::optional>> const& optionalChoiceLabeling) // The std::move call must be repeated here because otherwise this calls the copy constructor of the Base Class : AbstractNondeterministicModel(std::move(probabilityMatrix), std::move(stateLabeling), std::move(nondeterministicChoiceIndices), std::move(optionalStateRewardVector), std::move(optionalTransitionRewardMatrix), std::move(optionalChoiceLabeling)) { if (!this->checkValidityOfProbabilityMatrix()) { LOG4CPLUS_ERROR(logger, "Probability matrix is invalid."); throw storm::exceptions::InvalidArgumentException() << "Probability matrix is invalid."; } } /*! * Copy Constructor. Performs a deep copy of the given CTMDP. * @param ctmdp A reference to the CTMDP that is to be copied. */ Ctmdp(Ctmdp const & ctmdp) : AbstractNondeterministicModel(ctmdp) { if (!this->checkValidityOfProbabilityMatrix()) { LOG4CPLUS_ERROR(logger, "Probability matrix is invalid."); throw storm::exceptions::InvalidArgumentException() << "Probability matrix is invalid."; } } /*! * Move Constructor. Performs a move on the given CTMDP. * @param ctmdp A reference to the CTMDP that is to be moved. */ Ctmdp(Ctmdp&& ctmdp) : AbstractNondeterministicModel(std::move(ctmdp)) { if (!this->checkValidityOfProbabilityMatrix()) { LOG4CPLUS_ERROR(logger, "Probability matrix is invalid."); throw storm::exceptions::InvalidArgumentException() << "Probability matrix is invalid."; } } /*! * Destructor. */ ~Ctmdp() { // Intentionally left empty. } storm::models::ModelType getType() const { return CTMDP; } /*! * Calculates a hash over all values contained in this Model. * @return size_t A Hash Value */ virtual std::size_t getHash() const override { return AbstractNondeterministicModel::getHash(); } virtual std::shared_ptr> applyScheduler(storm::storage::Scheduler const& scheduler) const override { storm::storage::SparseMatrix newTransitionMatrix = storm::utility::matrix::applyScheduler(this->getTransitionMatrix(), this->getNondeterministicChoiceIndices(), scheduler); // Construct the new nondeterministic choice indices for the resulting matrix. std::vector nondeterministicChoiceIndices(this->getNumberOfStates() + 1); for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { nondeterministicChoiceIndices[state] = state; } nondeterministicChoiceIndices[this->getNumberOfStates()] = this->getNumberOfStates(); return std::shared_ptr>(new Ctmdp(newTransitionMatrix, this->getStateLabeling(), nondeterministicChoiceIndices, this->hasStateRewards() ? this->getStateRewardVector() : boost::optional>(), this->hasTransitionRewards() ? this->getTransitionRewardMatrix() : boost::optional>(), this->hasChoiceLabeling() ? this->getChoiceLabeling() : boost::optional>>())); } private: /*! * @brief Perform some sanity checks. * * Checks probability matrix if all rows sum up to one. */ bool checkValidityOfProbabilityMatrix() { // Get the settings object to customize linear solving. storm::settings::Settings* s = storm::settings::Settings::getInstance(); double precision = s->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); for (uint_fast64_t row = 0; row < this->getTransitionMatrix().getRowCount(); row++) { T sum = this->getTransitionMatrix().getRowSum(row); if (sum == 0) continue; if (std::abs(sum - 1) > precision) return false; } return true; } }; } // namespace models } // namespace storm #endif /* STORM_MODELS_CTMDP_H_ */