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.
 
 
 
 

199 lines
9.3 KiB

#include "src/builder/jit/StateBehaviour.h"
#include "src/adapters/CarlAdapter.h"
#include "src/utility/constants.h"
namespace storm {
namespace builder {
namespace jit {
template <typename IndexType, typename ValueType>
StateBehaviour<IndexType, ValueType>::StateBehaviour() : expanded(false) {
// Intentionally left empty.
}
template <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::addChoice(Choice<IndexType, ValueType>&& choice) {
choices.emplace_back(std::move(choice));
}
template <typename IndexType, typename ValueType>
Choice<IndexType, ValueType>& StateBehaviour<IndexType, ValueType>::addChoice(bool markovian) {
choices.emplace_back(markovian);
return choices.back();
}
template <typename IndexType, typename ValueType>
typename StateBehaviour<IndexType, ValueType>::ContainerType const& StateBehaviour<IndexType, ValueType>::getChoices() const {
return choices;
}
template <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::addStateReward(ValueType const& stateReward) {
stateRewards.push_back(stateReward);
}
template <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::addStateRewards(std::vector<ValueType>&& stateRewards) {
this->stateRewards = std::move(stateRewards);
}
template <typename IndexType, typename ValueType>
std::vector<ValueType> const& StateBehaviour<IndexType, ValueType>::getStateRewards() const {
return stateRewards;
}
template <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::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 <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::reduceDeterministic(storm::jani::ModelType const& modelType) {
std::size_t totalCount = choices.size();
ValueType totalExitRate = modelType == storm::jani::ModelType::DTMC ? static_cast<ValueType>(totalCount) : storm::utility::zero<ValueType>();
if (choices.front().getNumberOfRewards() > 0) {
std::vector<ValueType> newRewards(choices.front().getNumberOfRewards());
if (modelType == storm::jani::ModelType::CTMC) {
for (auto const& choice : choices) {
ValueType massOfChoice = storm::utility::zero<ValueType>();
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<ValueType>(totalCount));
}
}
template <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::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<IndexType, ValueType>& 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 <typename IndexType, typename ValueType>
bool StateBehaviour<IndexType, ValueType>::isHybrid() const {
return choices.size() > 1 && choices.front().isMarkovian() && !choices.back().isMarkovian();
}
template <typename IndexType, typename ValueType>
bool StateBehaviour<IndexType, ValueType>::isMarkovian() const {
return choices.size() == 1 && choices.front().isMarkovian();
}
template <typename IndexType, typename ValueType>
bool StateBehaviour<IndexType, ValueType>::isMarkovianOrHybrid() const {
return choices.front().isMarkovian();
}
template <typename IndexType, typename ValueType>
bool StateBehaviour<IndexType, ValueType>::isExpanded() const {
return expanded;
}
template <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::setExpanded() {
expanded = true;
}
template <typename IndexType, typename ValueType>
bool StateBehaviour<IndexType, ValueType>::empty() const {
return choices.empty();
}
template <typename IndexType, typename ValueType>
std::size_t StateBehaviour<IndexType, ValueType>::size() const {
return choices.size();
}
template <typename IndexType, typename ValueType>
void StateBehaviour<IndexType, ValueType>::clear() {
choices.clear();
stateRewards.clear();
expanded = false;
}
template class StateBehaviour<uint32_t, double>;
template class StateBehaviour<uint32_t, storm::RationalNumber>;
template class StateBehaviour<uint32_t, storm::RationalFunction>;
}
}
}