#include "src/builder/jit/StateBehaviour.h" #include "src/adapters/CarlAdapter.h" #include "src/utility/constants.h" namespace storm { namespace builder { namespace jit { template StateBehaviour::StateBehaviour() : expanded(false) { // Intentionally left empty. } template void StateBehaviour::addChoice(Choice&& choice) { choices.emplace_back(std::move(choice)); } template Choice& StateBehaviour::addChoice(bool markovian) { choices.emplace_back(markovian); return choices.back(); } template typename StateBehaviour::ContainerType const& StateBehaviour::getChoices() const { return choices; } template void StateBehaviour::addStateReward(ValueType const& stateReward) { stateRewards.push_back(stateReward); } template void StateBehaviour::addStateRewards(std::vector&& stateRewards) { this->stateRewards = std::move(stateRewards); } template std::vector const& StateBehaviour::getStateRewards() const { return stateRewards; } template void StateBehaviour::reduce(storm::jani::ModelType const& modelType) { if (choices.size() > 1) { if (modelType == storm::jani::ModelType::DTMC || modelType == storm::jani::ModelType::CTMC) { reduceDeterministic(modelType); } else if (modelType == storm::jani::ModelType::MA) { reduceMarkovAutomaton(); } else { for (auto& choice : choices) { choice.compress(); } } } else if (choices.size() == 1) { choices.front().compress(); } } template void StateBehaviour::reduceDeterministic(storm::jani::ModelType const& modelType) { std::size_t totalCount = choices.size(); ValueType totalExitRate = modelType == storm::jani::ModelType::DTMC ? static_cast(totalCount) : storm::utility::zero(); if (choices.front().getNumberOfRewards() > 0) { std::vector newRewards(choices.front().getNumberOfRewards()); if (modelType == storm::jani::ModelType::CTMC) { for (auto const& choice : choices) { ValueType massOfChoice = storm::utility::zero(); for (auto const& entry : choices.front().getDistribution()) { massOfChoice += entry.getValue(); } auto outIt = newRewards.begin(); for (auto const& reward : choice.getRewards()) { *outIt += reward * massOfChoice / totalExitRate; ++outIt; } } } else { for (auto const& choice : choices) { auto outIt = newRewards.begin(); for (auto const& reward : choice.getRewards()) { *outIt += reward / totalExitRate; ++outIt; } } } choices.front().setRewards(std::move(newRewards)); } for (auto it = ++choices.begin(), ite = choices.end(); it != ite; ++it) { choices.front().add(std::move(*it)); } choices.resize(1); choices.front().compress(); if (modelType == storm::jani::ModelType::DTMC) { choices.front().divideDistribution(static_cast(totalCount)); } } template void StateBehaviour::reduceMarkovAutomaton() { // If the model we build is a Markov Automaton, we reduce the choices by summing all Markovian choices // and making the Markovian choice the very first one (if there is any). bool foundPreviousMarkovianChoice = false; uint64_t numberOfChoicesToDelete = 0; for (uint_fast64_t index = 0; index + numberOfChoicesToDelete < this->size();) { Choice& choice = choices[index]; if (choice.isMarkovian()) { if (foundPreviousMarkovianChoice) { // If there was a previous Markovian choice, we need to sum them. Note that we can assume // that the previous Markovian choice is the very first one in the choices vector. choices.front().add(std::move(choice)); // Swap the choice to the end to indicate it can be removed (if it's not already there). if (index != this->size() - 1) { choice = std::move(choices[choices.size() - 1 - numberOfChoicesToDelete]); } ++numberOfChoicesToDelete; } else { // If there is no previous Markovian choice, just move the Markovian choice to the front. if (index != 0) { std::swap(choices.front(), choice); } foundPreviousMarkovianChoice = true; ++index; } } else { ++index; } } // Finally remove the choices that were added to other Markovian choices. if (numberOfChoicesToDelete > 0) { choices.resize(choices.size() - numberOfChoicesToDelete); } } template bool StateBehaviour::isHybrid() const { return choices.size() > 1 && choices.front().isMarkovian() && !choices.back().isMarkovian(); } template bool StateBehaviour::isMarkovian() const { return choices.size() == 1 && choices.front().isMarkovian(); } template bool StateBehaviour::isMarkovianOrHybrid() const { return choices.front().isMarkovian(); } template bool StateBehaviour::isExpanded() const { return expanded; } template void StateBehaviour::setExpanded() { expanded = true; } template bool StateBehaviour::empty() const { return choices.empty(); } template std::size_t StateBehaviour::size() const { return choices.size(); } template void StateBehaviour::clear() { choices.clear(); stateRewards.clear(); expanded = false; } template class StateBehaviour; template class StateBehaviour; template class StateBehaviour; } } }