#include "storm/generator/Choice.h" #include #include "storm/adapters/CarlAdapter.h" #include "storm/utility/constants.h" #include "storm/builder/ChoiceInformationBuilder.h" #include "storm/utility/macros.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/exceptions/NotImplementedException.h" namespace storm { namespace generator { template Choice::Choice(uint_fast64_t actionIndex, bool markovian) : markovian(markovian), actionIndex(actionIndex), distribution(), totalMass(storm::utility::zero()), rewards(), labels() { // Intentionally left empty. } template void Choice::add(Choice const& other) { STORM_LOG_THROW(this->markovian == other.markovian, storm::exceptions::InvalidOperationException, "Type of choices do not match."); STORM_LOG_THROW(this->actionIndex == other.actionIndex, storm::exceptions::InvalidOperationException, "Action index of choices do not match."); STORM_LOG_THROW(this->rewards.size() == other.rewards.size(), storm::exceptions::InvalidOperationException, "Reward value sizes of choices do not match."); // Add the elements to the distribution. this->distribution.add(other.distribution); // Update the total mass of the choice. this->totalMass += other.totalMass; // Add all reward values. auto otherRewIt = other.rewards.begin(); for (auto& rewardValue : this->rewards) { rewardValue += *otherRewIt; } // Join label sets and origin data if given. if (other.labels) { this->addLabels(other.labels.get()); } if (other.originData) { this->addOriginData(other.originData.get()); } } template typename storm::storage::Distribution::iterator Choice::begin() { return distribution.begin(); } template typename storm::storage::Distribution::const_iterator Choice::begin() const { return distribution.cbegin(); } template typename storm::storage::Distribution::iterator Choice::end() { return distribution.end(); } template typename storm::storage::Distribution::const_iterator Choice::end() const { return distribution.cend(); } template void Choice::addLabel(std::string const& newLabel) { if (!labels) { labels = std::set(); } labels->insert(newLabel); } template void Choice::addLabels(std::set const& newLabels) { if (labels) { labels->insert(newLabels.begin(), newLabels.end()); } else { labels = newLabels; } } template bool Choice::hasLabels() const { return labels.is_initialized(); } template std::set const& Choice::getLabels() const { return labels.get(); } template void Choice::addOriginData(boost::any const& data) { if (!this->originData || this->originData->empty()) { this->originData = data; } else { if (!data.empty()) { // Reaching this point means that the both the existing and the given data are non-empty auto existingDataAsIndexSet = boost::any_cast>(&this->originData.get()); if (existingDataAsIndexSet != nullptr) { auto givenDataAsIndexSet = boost::any_cast>(&data); STORM_LOG_THROW(givenDataAsIndexSet != nullptr, storm::exceptions::InvalidOperationException, "Types of existing and given choice origin data do not match."); existingDataAsIndexSet->insert(givenDataAsIndexSet->begin(), givenDataAsIndexSet->end()); } else { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Type of choice origin data (aka " << data.type().name() << ") is not implemented."); } } } } template bool Choice::hasOriginData() const { return originData.is_initialized(); } template boost::any const& Choice::getOriginData() const { return originData.get(); } template uint_fast64_t Choice::getActionIndex() const { return actionIndex; } template ValueType Choice::getTotalMass() const { return totalMass; } template void Choice::addProbability(StateType const& state, ValueType const& value) { totalMass += value; distribution.addProbability(state, value); } template void Choice::addReward(ValueType const& value) { rewards.push_back(value); } template void Choice::addRewards(std::vector&& values) { this->rewards = std::move(values); } template std::vector const& Choice::getRewards() const { return rewards; } template bool Choice::isMarkovian() const { return markovian; } template std::size_t Choice::size() const { return distribution.size(); } template std::ostream& operator<<(std::ostream& out, Choice const& choice) { out << "<"; for (auto const& stateProbabilityPair : choice) { out << stateProbabilityPair.first << " : " << stateProbabilityPair.second << ", "; } out << ">"; return out; } template class Choice; #ifdef STORM_HAVE_CARL template class Choice; template class Choice; #endif } }