|
@ -1,3 +1,5 @@ |
|
|
|
|
|
#include <queue>
|
|
|
|
|
|
|
|
|
#include "storm/models/sparse/MarkovAutomaton.h"
|
|
|
#include "storm/models/sparse/MarkovAutomaton.h"
|
|
|
|
|
|
|
|
|
#include "storm/adapters/RationalFunctionAdapter.h"
|
|
|
#include "storm/adapters/RationalFunctionAdapter.h"
|
|
@ -265,6 +267,108 @@ namespace storm { |
|
|
return std::make_shared<storm::models::sparse::Ctmc<ValueType, RewardModelType>>(std::move(rateMatrix), std::move(stateLabeling)); |
|
|
return std::make_shared<storm::models::sparse::Ctmc<ValueType, RewardModelType>>(std::move(rateMatrix), std::move(stateLabeling)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<typename ValueType, typename RewardModelType> |
|
|
|
|
|
std::shared_ptr<MarkovAutomaton<ValueType, RewardModelType>> |
|
|
|
|
|
MarkovAutomaton<ValueType, RewardModelType>::eliminateNonmarkovianStates() const { |
|
|
|
|
|
if (isClosed() && markovianStates.full()) { |
|
|
|
|
|
storm::storage::sparse::ModelComponents<ValueType, RewardModelType> components( |
|
|
|
|
|
this->getTransitionMatrix(), this->getStateLabeling(), this->getRewardModels(), false); |
|
|
|
|
|
components.exitRates = this->getExitRates(); |
|
|
|
|
|
if (this->hasChoiceLabeling()) { |
|
|
|
|
|
components.choiceLabeling = this->getChoiceLabeling(); |
|
|
|
|
|
} |
|
|
|
|
|
if (this->hasStateValuations()) { |
|
|
|
|
|
components.stateValuations = this->getStateValuations(); |
|
|
|
|
|
} |
|
|
|
|
|
if (this->hasChoiceOrigins()) { |
|
|
|
|
|
components.choiceOrigins = this->getChoiceOrigins(); |
|
|
|
|
|
} |
|
|
|
|
|
return std::make_shared<MarkovAutomaton<ValueType, RewardModelType>>(std::move(components)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::map<uint_fast64_t, uint_fast64_t> stateRemapping; |
|
|
|
|
|
std::set<uint_fast64_t> statesToKeep; |
|
|
|
|
|
std::queue<uint_fast64_t> changedStates; |
|
|
|
|
|
std::queue<uint_fast64_t> queue; |
|
|
|
|
|
|
|
|
|
|
|
storm::storage::SparseMatrix<ValueType> backwards = this->getBackwardTransitions(); |
|
|
|
|
|
|
|
|
|
|
|
// Determine the state remapping
|
|
|
|
|
|
// TODO Consider state labels
|
|
|
|
|
|
for (uint_fast64_t base_state = 0; base_state < this->getNumberOfStates(); ++base_state) { |
|
|
|
|
|
STORM_LOG_ASSERT(!this->isHybridState(base_state), "Base state is hybrid."); |
|
|
|
|
|
if (this->isMarkovianState(base_state)) { |
|
|
|
|
|
queue.push(base_state); |
|
|
|
|
|
|
|
|
|
|
|
while (!queue.empty()) { |
|
|
|
|
|
auto currState = queue.front(); |
|
|
|
|
|
queue.pop(); |
|
|
|
|
|
// Get predecessors from matrix
|
|
|
|
|
|
typename storm::storage::SparseMatrix<ValueType>::rows entriesInRow = backwards.getRow( |
|
|
|
|
|
currState); |
|
|
|
|
|
for (auto entryIt = entriesInRow.begin(), entryIte = entriesInRow.end(); |
|
|
|
|
|
entryIt != entryIte; ++entryIt) { |
|
|
|
|
|
uint_fast64_t predecessor = entryIt->getColumn(); |
|
|
|
|
|
if (!this->isMarkovianState(predecessor) && !statesToKeep.count(predecessor)) { |
|
|
|
|
|
if (!stateRemapping.count(predecessor)) { |
|
|
|
|
|
stateRemapping[predecessor] = base_state; |
|
|
|
|
|
queue.push(predecessor); |
|
|
|
|
|
} else if (stateRemapping[predecessor] != base_state) { |
|
|
|
|
|
stateRemapping.erase(predecessor); |
|
|
|
|
|
statesToKeep.insert(predecessor); |
|
|
|
|
|
changedStates.push(predecessor); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Correct the mapping with the states which have to be kept
|
|
|
|
|
|
while (!changedStates.empty()) { |
|
|
|
|
|
uint_fast64_t base_state = changedStates.front(); |
|
|
|
|
|
queue.push(base_state); |
|
|
|
|
|
|
|
|
|
|
|
while (!queue.empty()) { |
|
|
|
|
|
auto currState = queue.front(); |
|
|
|
|
|
queue.pop(); |
|
|
|
|
|
// Get predecessors from matrix
|
|
|
|
|
|
typename storm::storage::SparseMatrix<ValueType>::rows entriesInRow = backwards.getRow( |
|
|
|
|
|
currState); |
|
|
|
|
|
for (auto entryIt = entriesInRow.begin(), entryIte = entriesInRow.end(); |
|
|
|
|
|
entryIt != entryIte; ++entryIt) { |
|
|
|
|
|
uint_fast64_t predecessor = entryIt->getColumn(); |
|
|
|
|
|
if (!this->isMarkovianState(predecessor) && !statesToKeep.count(predecessor)) { |
|
|
|
|
|
if (!stateRemapping.count(predecessor)) { |
|
|
|
|
|
stateRemapping[predecessor] = base_state; |
|
|
|
|
|
queue.push(predecessor); |
|
|
|
|
|
} else if (stateRemapping[predecessor] != base_state) { |
|
|
|
|
|
stateRemapping.erase(predecessor); |
|
|
|
|
|
statesToKeep.insert(predecessor); |
|
|
|
|
|
changedStates.push(predecessor); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
changedStates.pop(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// At this point, we hopefully have a valid mapping which eliminates a lot of states
|
|
|
|
|
|
|
|
|
|
|
|
STORM_PRINT("Remapping \n") |
|
|
|
|
|
for (auto entry : stateRemapping) { |
|
|
|
|
|
STORM_PRINT(std::to_string(entry.first) << " -> " << std::to_string(entry.second) << "\n") |
|
|
|
|
|
} |
|
|
|
|
|
STORM_PRINT("Remapped States: " << stateRemapping.size() << "\n") |
|
|
|
|
|
// TODO test some examples, especially ones containing non-determinism
|
|
|
|
|
|
|
|
|
|
|
|
// Build the new matrix
|
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
|
|
|
|
return nullptr; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename ValueType, typename RewardModelType> |
|
|
template<typename ValueType, typename RewardModelType> |
|
|
void MarkovAutomaton<ValueType, RewardModelType>::printModelInformationToStream(std::ostream& out) const { |
|
|
void MarkovAutomaton<ValueType, RewardModelType>::printModelInformationToStream(std::ostream& out) const { |
|
@ -278,9 +382,11 @@ namespace storm { |
|
|
|
|
|
|
|
|
template class MarkovAutomaton<double>; |
|
|
template class MarkovAutomaton<double>; |
|
|
#ifdef STORM_HAVE_CARL
|
|
|
#ifdef STORM_HAVE_CARL
|
|
|
|
|
|
|
|
|
template class MarkovAutomaton<storm::RationalNumber>; |
|
|
template class MarkovAutomaton<storm::RationalNumber>; |
|
|
|
|
|
|
|
|
template class MarkovAutomaton<double, storm::models::sparse::StandardRewardModel<storm::Interval>>; |
|
|
template class MarkovAutomaton<double, storm::models::sparse::StandardRewardModel<storm::Interval>>; |
|
|
|
|
|
|
|
|
template class MarkovAutomaton<storm::RationalFunction>; |
|
|
template class MarkovAutomaton<storm::RationalFunction>; |
|
|
#endif
|
|
|
#endif
|
|
|
} // namespace sparse
|
|
|
} // namespace sparse
|