Browse Source

some refactoring of state-elimination-related things

Former-commit-id: c51fd9c47c
main
dehnert 9 years ago
parent
commit
8ce9e56af8
  1. 4
      src/adapters/EigenAdapter.cpp
  2. 268
      src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp
  3. 67
      src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h
  4. 4
      src/models/sparse/MarkovAutomaton.cpp
  5. 56
      src/solver/stateelimination/ConditionalEliminator.cpp
  6. 29
      src/solver/stateelimination/ConditionalEliminator.h
  7. 75
      src/solver/stateelimination/DynamicStatePriorityQueue.cpp
  8. 48
      src/solver/stateelimination/DynamicStatePriorityQueue.h
  9. 39
      src/solver/stateelimination/LongRunAverageEliminator.cpp
  10. 20
      src/solver/stateelimination/LongRunAverageEliminator.h
  11. 46
      src/solver/stateelimination/MAEliminator.cpp
  12. 32
      src/solver/stateelimination/MAEliminator.h
  13. 46
      src/solver/stateelimination/PrioritizedEliminator.cpp
  14. 35
      src/solver/stateelimination/PrioritizedEliminator.h
  15. 39
      src/solver/stateelimination/PrioritizedStateEliminator.cpp
  16. 33
      src/solver/stateelimination/PrioritizedStateEliminator.h
  17. 64
      src/solver/stateelimination/StateEliminator.cpp
  18. 29
      src/solver/stateelimination/StateEliminator.h
  19. 13
      src/solver/stateelimination/StatePriorityQueue.cpp
  20. 21
      src/solver/stateelimination/StatePriorityQueue.h
  21. 28
      src/solver/stateelimination/StaticStatePriorityQueue.cpp
  22. 26
      src/solver/stateelimination/StaticStatePriorityQueue.h
  23. 160
      src/utility/stateelimination.cpp
  24. 60
      src/utility/stateelimination.h

4
src/adapters/EigenAdapter.cpp

@ -4,7 +4,7 @@ namespace storm {
namespace adapters {
template<typename ValueType>
static std::unique_ptr<Eigen::SparseMatrix<ValueType>> toEigenSparseMatrix(storm::storage::SparseMatrix<ValueType> const& matrix) {
std::unique_ptr<Eigen::SparseMatrix<ValueType>> EigenAdapter::toEigenSparseMatrix(storm::storage::SparseMatrix<ValueType> const& matrix) {
// Build a list of triplets and let Eigen care about the insertion.
std::vector<Eigen::Triplet<ValueType>> triplets;
triplets.reserve(matrix.getNonzeroEntryCount());
@ -20,6 +20,6 @@ namespace storm {
return result;
}
template std::unique_ptr<Eigen::SparseMatrix<double>> toEigenSparseMatrix(storm::storage::SparseMatrix<double> const& matrix);
template std::unique_ptr<Eigen::SparseMatrix<double>> EigenAdapter::toEigenSparseMatrix(storm::storage::SparseMatrix<double> const& matrix);
}
}

268
src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp

@ -18,67 +18,27 @@
#include "src/logic/FragmentSpecification.h"
#include "src/solver/stateelimination/LongRunAverageEliminator.h"
#include "src/solver/stateelimination/ConditionalEliminator.h"
#include "src/solver/stateelimination/PrioritizedStateEliminator.h"
#include "src/solver/stateelimination/StaticStatePriorityQueue.h"
#include "src/solver/stateelimination/DynamicStatePriorityQueue.h"
#include "src/utility/stateelimination.h"
#include "src/utility/graph.h"
#include "src/utility/vector.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
#include "src/exceptions/InvalidPropertyException.h"
#include "src/exceptions/InvalidStateException.h"
#include "src/exceptions/InvalidSettingsException.h"
#include "src/exceptions/IllegalArgumentException.h"
#include "src/solver/stateelimination/LongRunAverageEliminator.h"
#include "src/solver/stateelimination/ConditionalEliminator.h"
#include "src/solver/stateelimination/PrioritizedEliminator.h"
namespace storm {
namespace modelchecker {
template<typename ValueType>
uint_fast64_t estimateComplexity(ValueType const& value) {
return 1;
}
#ifdef STORM_HAVE_CARL
template<>
uint_fast64_t estimateComplexity(storm::RationalFunction const& value) {
if (storm::utility::isConstant(value)) {
return 1;
}
if (value.denominator().isConstant()) {
return value.nominator().complexity();
} else {
return value.denominator().complexity() * value.nominator().complexity();
}
}
#endif
bool eliminationOrderNeedsDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Backward ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
}
bool eliminationOrderNeedsForwardDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed;
}
bool eliminationOrderNeedsReversedDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
}
bool eliminationOrderIsPenaltyBased(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::DynamicPenalty ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression;
}
bool eliminationOrderIsStatic(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return eliminationOrderNeedsDistances(order) || order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty;
}
using namespace storm::utility::stateelimination;
template<typename SparseDtmcModelType>
SparseDtmcEliminationModelChecker<SparseDtmcModelType>::SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc<ValueType> const& model) : SparsePropositionalModelChecker<SparseDtmcModelType>(model) {
@ -265,11 +225,11 @@ namespace storm {
std::vector<ValueType> averageTimeInStates(stateValues.size(), storm::utility::one<ValueType>());
// First, we eliminate all states in BSCCs (except for the representative states).
std::shared_ptr<StatePriorityQueue<ValueType>> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs);
storm::solver::stateelimination::LongRunAverageEliminator<SparseDtmcModelType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue, stateValues, averageTimeInStates);
std::shared_ptr<StatePriorityQueue> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs);
storm::solver::stateelimination::LongRunAverageEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue, stateValues, averageTimeInStates);
while (priorityQueue->hasNextState()) {
storm::storage::sparse::state_type state = priorityQueue->popNextState();
while (priorityQueue->hasNext()) {
storm::storage::sparse::state_type state = priorityQueue->pop();
stateEliminator.eliminateState(state, true);
#ifdef STORM_DEV
STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions), "The forward and backward transition matrices became inconsistent.");
@ -711,21 +671,21 @@ namespace storm {
storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
if (eliminationOrderNeedsDistances(order)) {
distanceBasedPriorities = getDistanceBasedPriorities(submatrix, submatrixTransposed, newInitialStates, oneStepProbabilities,
eliminationOrderNeedsForwardDistances(order),
eliminationOrderNeedsReversedDistances(order));
eliminationOrderNeedsForwardDistances(order),
eliminationOrderNeedsReversedDistances(order));
}
storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(submatrix);
storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(submatrixTransposed, true);
std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
STORM_LOG_INFO("Computing conditional probilities." << std::endl);
uint_fast64_t numberOfStatesToEliminate = statePriorities->size();
STORM_LOG_INFO("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl);
performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(), true);
storm::solver::stateelimination::ConditionalEliminator<SparseDtmcModelType> stateEliminator = storm::solver::stateelimination::ConditionalEliminator<SparseDtmcModelType>(flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, phiStates, psiStates);
storm::solver::stateelimination::ConditionalEliminator<ValueType> stateEliminator = storm::solver::stateelimination::ConditionalEliminator<ValueType>(flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, phiStates, psiStates);
// Eliminate the transitions going into the initial state (if there are any).
if (!flexibleBackwardTransitions.getRow(*newInitialStates.begin()).empty()) {
@ -752,6 +712,7 @@ namespace storm {
// to eliminate all chains of non-psi states between the current state and psi states.
bool hasNonPsiSuccessor = true;
while (hasNonPsiSuccessor) {
stateEliminator.setFilterPhi();
hasNonPsiSuccessor = false;
// Only treat the state if it has an outgoing transition other than a self-loop.
@ -764,9 +725,7 @@ namespace storm {
// Eliminate the successor only if there possibly is a psi state reachable through it.
if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
STORM_LOG_TRACE("Found non-psi successor " << element.getColumn() << " that needs to be eliminated.");
stateEliminator.setStatePhi();
stateEliminator.eliminateState(element.getColumn(), false);
stateEliminator.clearState();
hasNonPsiSuccessor = true;
}
}
@ -774,6 +733,7 @@ namespace storm {
STORM_LOG_ASSERT(!flexibleMatrix.getRow(initialStateSuccessor).empty(), "(1) New transitions expected to be non-empty.");
}
}
stateEliminator.unsetFilter();
} else {
STORM_LOG_ASSERT(psiStates.get(initialStateSuccessor), "Expected psi state.");
STORM_LOG_TRACE("Is a psi state.");
@ -784,6 +744,7 @@ namespace storm {
bool hasNonPhiSuccessor = true;
while (hasNonPhiSuccessor) {
stateEliminator.setFilterPsi();
hasNonPhiSuccessor = false;
// Only treat the state if it has an outgoing transition other than a self-loop.
@ -795,15 +756,14 @@ namespace storm {
FlexibleRowType const& successorRow = flexibleMatrix.getRow(element.getColumn());
if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
STORM_LOG_TRACE("Found non-phi successor " << element.getColumn() << " that needs to be eliminated.");
stateEliminator.setStatePsi();
stateEliminator.eliminateState(element.getColumn(), false);
stateEliminator.clearState();
hasNonPhiSuccessor = true;
}
}
}
}
}
stateEliminator.unsetFilter();
}
}
@ -844,62 +804,12 @@ namespace storm {
}
template<typename SparseDtmcModelType>
std::shared_ptr<StatePriorityQueue<typename SparseDtmcModelType::ValueType>> SparseDtmcEliminationModelChecker<SparseDtmcModelType>::createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states) {
void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) {
STORM_LOG_TRACE("Creating state priority queue for states " << states);
storm::solver::stateelimination::PrioritizedStateEliminator<ValueType> stateEliminator(transitionMatrix, backwardTransitions, priorityQueue, values);
// Get the settings to customize the priority queue.
storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
if (order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Random) {
std::random_device randomDevice;
std::mt19937 generator(randomDevice());
std::shuffle(sortedStates.begin(), sortedStates.end(), generator);
return std::make_unique<StaticStatePriorityQueue>(sortedStates);
} else {
if (eliminationOrderNeedsDistances(order)) {
STORM_LOG_THROW(static_cast<bool>(distanceBasedStatePriorities), storm::exceptions::InvalidStateException, "Unable to build state priority queue without distance-based priorities.");
std::sort(sortedStates.begin(), sortedStates.end(), [&distanceBasedStatePriorities] (storm::storage::sparse::state_type const& state1, storm::storage::sparse::state_type const& state2) { return distanceBasedStatePriorities.get()[state1] < distanceBasedStatePriorities.get()[state2]; } );
return std::make_unique<StaticStatePriorityQueue>(sortedStates);
} else if (eliminationOrderIsPenaltyBased(order)) {
std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> statePenalties(sortedStates.size());
PenaltyFunctionType penaltyFunction = order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression ? computeStatePenaltyRegularExpression : computeStatePenalty;
for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
statePenalties[index] = std::make_pair(sortedStates[index], penaltyFunction(sortedStates[index], transitionMatrix, backwardTransitions, oneStepProbabilities));
}
std::sort(statePenalties.begin(), statePenalties.end(), [] (std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty1, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty2) { return statePenalty1.second < statePenalty2.second; } );
if (eliminationOrderIsStatic(order)) {
// For the static penalty version, we need to strip the penalties to create the queue.
for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
sortedStates[index] = statePenalties[index].first;
}
return std::make_unique<StaticStatePriorityQueue>(sortedStates);
} else {
// For the dynamic penalty version, we need to give the full state-penalty pairs.
return std::make_unique<DynamicPenaltyStatePriorityQueue>(statePenalties, penaltyFunction);
}
}
}
STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Illegal elimination order selected.");
}
template<typename SparseDtmcModelType>
std::shared_ptr<StatePriorityQueue<typename SparseDtmcModelType::ValueType>> SparseDtmcEliminationModelChecker<SparseDtmcModelType>::createNaivePriorityQueue(storm::storage::BitVector const& states) {
std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
return std::shared_ptr<StatePriorityQueue<ValueType>>(new StaticStatePriorityQueue(sortedStates));
}
template<typename SparseDtmcModelType>
void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue<ValueType>>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) {
storm::solver::stateelimination::PrioritizedEliminator<SparseDtmcModelType> stateEliminator(transitionMatrix, backwardTransitions, priorityQueue, values);
while (priorityQueue->hasNextState()) {
storm::storage::sparse::state_type state = priorityQueue->popNextState();
while (priorityQueue->hasNext()) {
storm::storage::sparse::state_type state = priorityQueue->pop();
bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.get(state);
stateEliminator.eliminateState(state, removeForwardTransitions);
if (removeForwardTransitions) {
@ -913,7 +823,7 @@ namespace storm {
template<typename SparseDtmcModelType>
void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector<ValueType>& values, boost::optional<std::vector<uint_fast64_t>> const& distanceBasedPriorities) {
std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem);
std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem);
std::size_t numberOfStatesToEliminate = statePriorities->size();
STORM_LOG_DEBUG("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl);
@ -932,7 +842,7 @@ namespace storm {
if (storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().isEliminateEntryStatesLastSet()) {
STORM_LOG_DEBUG("Eliminating " << entryStateQueue.size() << " entry states as a last step.");
std::vector<storm::storage::sparse::state_type> sortedStates(entryStateQueue.begin(), entryStateQueue.end());
std::shared_ptr<StatePriorityQueue<ValueType>> queuePriorities = std::shared_ptr<StatePriorityQueue<ValueType>>(new StaticStatePriorityQueue(sortedStates));
std::shared_ptr<StatePriorityQueue> queuePriorities = std::make_shared<StaticStatePriorityQueue>(sortedStates);
performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
}
STORM_LOG_DEBUG("Eliminated " << subsystem.size() << " states." << std::endl);
@ -1000,7 +910,7 @@ namespace storm {
}
}
std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs);
std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs);
STORM_LOG_TRACE("Eliminating " << statePriorities->size() << " trivial SCCs.");
performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
STORM_LOG_TRACE("Eliminated all trivial SCCs.");
@ -1030,7 +940,7 @@ namespace storm {
} else {
// In this case, we perform simple state elimination in the current SCC.
STORM_LOG_TRACE("SCC of size " << scc.getNumberOfSetBits() << " is small enough to be eliminated directly.");
std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates);
std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates);
performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
STORM_LOG_TRACE("Eliminated all states of SCC.");
}
@ -1038,7 +948,7 @@ namespace storm {
// Finally, eliminate the entry states (if we are required to do so).
if (eliminateEntryStates) {
STORM_LOG_TRACE("Finally, eliminating entry states.");
std::shared_ptr<StatePriorityQueue<ValueType>> naivePriorities = createNaivePriorityQueue(entryStates);
std::shared_ptr<StatePriorityQueue> naivePriorities = createNaivePriorityQueue(entryStates);
performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
STORM_LOG_TRACE("Eliminated/added entry states.");
} else {
@ -1098,120 +1008,6 @@ namespace storm {
}
}
template<typename SparseDtmcModelType>
uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
uint_fast64_t penalty = 0;
bool hasParametricSelfLoop = false;
for (auto const& predecessor : backwardTransitions.getRow(state)) {
for (auto const& successor : transitionMatrix.getRow(state)) {
penalty += estimateComplexity(predecessor.getValue()) * estimateComplexity(successor.getValue());
// STORM_LOG_TRACE("1) penalty += " << (estimateComplexity(predecessor.getValue()) * estimateComplexity(successor.getValue())) << " because of " << predecessor.getValue() << " and " << successor.getValue() << ".");
}
if (predecessor.getColumn() == state) {
hasParametricSelfLoop = !storm::utility::isConstant(predecessor.getValue());
}
penalty += estimateComplexity(oneStepProbabilities[predecessor.getColumn()]) * estimateComplexity(predecessor.getValue()) * estimateComplexity(oneStepProbabilities[state]);
// STORM_LOG_TRACE("2) penalty += " << (estimateComplexity(oneStepProbabilities[predecessor.getColumn()]) * estimateComplexity(predecessor.getValue()) * estimateComplexity(oneStepProbabilities[state])) << " because of " << oneStepProbabilities[predecessor.getColumn()] << ", " << predecessor.getValue() << " and " << oneStepProbabilities[state] << ".");
}
// If it is a self-loop that is parametric, we increase the penalty a lot.
if (hasParametricSelfLoop) {
penalty *= 10;
// STORM_LOG_TRACE("3) penalty *= 100, because of parametric self-loop.");
}
// STORM_LOG_TRACE("New penalty of state " << state << " is " << penalty << ".");
return penalty;
}
template<typename SparseDtmcModelType>
uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
return backwardTransitions.getRow(state).size() * transitionMatrix.getRow(state).size();
}
template<typename ValueType>
void StatePriorityQueue<ValueType>::update(storm::storage::sparse::state_type, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
// Intentionally left empty.
}
template<typename SparseDtmcModelType>
SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates) : StatePriorityQueue<ValueType>(), sortedStates(sortedStates), currentPosition(0) {
// Intentionally left empty.
}
template<typename SparseDtmcModelType>
bool SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::hasNextState() const {
return currentPosition < sortedStates.size();
}
template<typename SparseDtmcModelType>
storm::storage::sparse::state_type SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::popNextState() {
++currentPosition;
return sortedStates[currentPosition - 1];
}
template<typename SparseDtmcModelType>
std::size_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::size() const {
return sortedStates.size() - currentPosition;
}
template<typename SparseDtmcModelType>
SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::DynamicPenaltyStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue<ValueType>(), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) {
// Insert all state-penalty pairs into our priority queue.
for (auto const& statePenalty : sortedStatePenaltyPairs) {
priorityQueue.insert(priorityQueue.end(), statePenalty);
}
// Insert all state-penalty pairs into auxiliary mapping.
for (auto const& statePenalty : sortedStatePenaltyPairs) {
stateToPriorityMapping.emplace(statePenalty);
}
}
template<typename SparseDtmcModelType>
bool SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::hasNextState() const {
return !priorityQueue.empty();
}
template<typename SparseDtmcModelType>
storm::storage::sparse::state_type SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::popNextState() {
auto it = priorityQueue.begin();
STORM_LOG_TRACE("Popping state " << it->first << " with priority " << it->second << ".");
storm::storage::sparse::state_type result = it->first;
priorityQueue.erase(priorityQueue.begin());
return result;
}
template<typename SparseDtmcModelType>
void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
// First, we need to find the priority until now.
auto priorityIt = stateToPriorityMapping.find(state);
// If the priority queue does not store the priority of the given state, we must not update it.
if (priorityIt == stateToPriorityMapping.end()) {
return;
}
uint_fast64_t lastPriority = priorityIt->second;
uint_fast64_t newPriority = penaltyFunction(state, transitionMatrix, backwardTransitions, oneStepProbabilities);
if (lastPriority != newPriority) {
// Erase and re-insert into the priority queue with the new priority.
auto queueIt = priorityQueue.find(std::make_pair(state, lastPriority));
priorityQueue.erase(queueIt);
priorityQueue.emplace(state, newPriority);
// Finally, update the probability in the mapping.
priorityIt->second = newPriority;
}
}
template<typename SparseDtmcModelType>
std::size_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::size() const {
return priorityQueue.size();
}
template<typename SparseDtmcModelType>
bool SparseDtmcEliminationModelChecker<SparseDtmcModelType>::checkConsistent(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) {
for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.getRowCount(); ++forwardIndex) {
@ -1235,13 +1031,9 @@ namespace storm {
return true;
}
template class StatePriorityQueue<double>;
template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<double>>;
template uint_fast64_t estimateComplexity(double const& value);
#ifdef STORM_HAVE_CARL
template class StatePriorityQueue<storm::RationalFunction>;
template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>>;
#endif
} // namespace modelchecker

67
src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h

@ -1,26 +1,18 @@
#ifndef STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCELIMINATIONMODELCHECKER_H_
#define STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCELIMINATIONMODELCHECKER_H_
#include "src/modelchecker/propositional/SparsePropositionalModelChecker.h"
#include "src/models/sparse/Dtmc.h"
#include "src/storage/sparse/StateType.h"
#include "src/storage/FlexibleSparseMatrix.h"
#include "src/models/sparse/Dtmc.h"
#include "src/modelchecker/propositional/SparsePropositionalModelChecker.h"
#include "src/utility/constants.h"
#include "src/solver/stateelimination/StatePriorityQueue.h"
namespace storm {
namespace modelchecker {
template<typename ValueType>
uint_fast64_t estimateComplexity(ValueType const& value);
template<typename ValueType>
class StatePriorityQueue {
public:
virtual bool hasNextState() const = 0;
virtual storm::storage::sparse::state_type popNextState() = 0;
virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
virtual std::size_t size() const = 0;
};
using namespace storm::solver::stateelimination;
template<typename SparseDtmcModelType>
class SparseDtmcEliminationModelChecker : public SparsePropositionalModelChecker<SparseDtmcModelType> {
@ -52,54 +44,13 @@ namespace storm {
static std::vector<ValueType> computeReachabilityRewards(storm::storage::SparseMatrix<ValueType> const& probabilityMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector<ValueType>& stateRewardValues, bool computeForInitialStatesOnly);
private:
class StaticStatePriorityQueue : public StatePriorityQueue<ValueType> {
public:
StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates);
virtual bool hasNextState() const override;
virtual storm::storage::sparse::state_type popNextState() override;
virtual std::size_t size() const override;
private:
std::vector<uint_fast64_t> sortedStates;
uint_fast64_t currentPosition;
};
struct PriorityComparator {
bool operator()(std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& first, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& second) {
return (first.second < second.second) || (first.second == second.second && first.first < second.first) ;
}
};
typedef std::function<uint_fast64_t (storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities)> PenaltyFunctionType;
class DynamicPenaltyStatePriorityQueue : public StatePriorityQueue<ValueType> {
public:
DynamicPenaltyStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction);
virtual bool hasNextState() const override;
virtual storm::storage::sparse::state_type popNextState() override;
virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) override;
virtual std::size_t size() const override;
private:
std::set<std::pair<storm::storage::sparse::state_type, uint_fast64_t>, PriorityComparator> priorityQueue;
std::unordered_map<storm::storage::sparse::state_type, uint_fast64_t> stateToPriorityMapping;
PenaltyFunctionType penaltyFunction;
};
static std::vector<ValueType> computeLongRunValues(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& maybeStates, bool computeResultsForInitialStatesOnly, std::vector<ValueType>& stateValues);
static std::vector<ValueType> computeReachabilityRewards(storm::storage::SparseMatrix<ValueType> const& probabilityMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, bool computeForInitialStatesOnly);
static std::vector<ValueType> computeReachabilityValues(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType>& values, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector<ValueType> const& oneStepProbabilitiesToTarget);
static std::shared_ptr<StatePriorityQueue<ValueType>> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& stateDistances, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states);
static std::shared_ptr<StatePriorityQueue<ValueType>> createNaivePriorityQueue(storm::storage::BitVector const& states);
static void performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue<ValueType>>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly);
static void performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly);
static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector<ValueType>& values, boost::optional<std::vector<ValueType>>& additionalStateValues, boost::optional<std::vector<uint_fast64_t>> const& distanceBasedPriorities);
@ -113,10 +64,6 @@ namespace storm {
static std::vector<std::size_t> getStateDistances(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector<ValueType> const& oneStepProbabilities, bool forward);
static uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
static uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
static bool checkConsistent(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions);
};

4
src/models/sparse/MarkovAutomaton.cpp

@ -5,7 +5,7 @@
#include "src/adapters/CarlAdapter.h"
#include "src/storage/FlexibleSparseMatrix.h"
#include "src/models/sparse/Dtmc.h"
#include "src/solver/stateelimination/MAEliminator.h"
#include "src/solver/stateelimination/StateEliminator.h"
#include "src/utility/vector.h"
namespace storm {
@ -273,7 +273,7 @@ namespace storm {
// Initialize
storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(this->getTransitionMatrix());
storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(this->getTransitionMatrix().transpose());
storm::solver::stateelimination::MAEliminator<storm::models::sparse::Dtmc<ValueType>> stateEliminator(flexibleMatrix, flexibleBackwardTransitions);
storm::solver::stateelimination::StateEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions);
for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) {
assert(!this->isHybridState(state));

56
src/solver/stateelimination/ConditionalEliminator.cpp

@ -1,35 +1,38 @@
#include "src/solver/stateelimination/ConditionalEliminator.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
ConditionalEliminator<SparseModelType>::ConditionalEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions), oneStepProbabilities(oneStepProbabilities), phiStates(phiStates), psiStates(psiStates), specificState(NONE) {
template<typename ValueType>
ConditionalEliminator<ValueType>::ConditionalEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates) : StateEliminator<ValueType>(transitionMatrix, backwardTransitions), oneStepProbabilities(oneStepProbabilities), phiStates(phiStates), psiStates(psiStates), filterLabel(StateLabel::NONE) {
}
template<typename SparseModelType>
void ConditionalEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
template<typename ValueType>
void ConditionalEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
oneStepProbabilities[state] = storm::utility::simplify(loopProbability * oneStepProbabilities[state]);
}
template<typename SparseModelType>
void ConditionalEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
template<typename ValueType>
void ConditionalEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
oneStepProbabilities[predecessor] = storm::utility::simplify(oneStepProbabilities[predecessor] * storm::utility::simplify(probability * oneStepProbabilities[state]));
}
template<typename SparseModelType>
void ConditionalEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
template<typename ValueType>
void ConditionalEliminator<ValueType>::updatePriority(storm::storage::sparse::state_type const& state) {
// Do nothing
}
template<typename SparseModelType>
bool ConditionalEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
template<typename ValueType>
bool ConditionalEliminator<ValueType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
// TODO find better solution than flag
switch (specificState) {
case PHI:
switch (filterLabel) {
case StateLabel::PHI:
return phiStates.get(state);
case PSI:
case StateLabel::PSI:
return psiStates.get(state);
default:
STORM_LOG_ASSERT(false, "Specific state not set.");
@ -37,16 +40,35 @@ namespace storm {
}
}
template<typename SparseModelType>
bool ConditionalEliminator<SparseModelType>::isFilterPredecessor() const {
template<typename ValueType>
bool ConditionalEliminator<ValueType>::isFilterPredecessor() const {
return true;
}
template<typename ValueType>
void ConditionalEliminator<ValueType>::setFilterPhi() {
filterLabel = StateLabel::PHI;
}
template<typename ValueType>
void ConditionalEliminator<ValueType>::setFilterPsi() {
filterLabel = StateLabel::PSI;
}
template<typename ValueType>
void ConditionalEliminator<ValueType>::setFilter(StateLabel const& stateLabel) {
filterLabel = stateLabel;
}
template<typename ValueType>
void ConditionalEliminator<ValueType>::unsetFilter() {
filterLabel = StateLabel::NONE;
}
template class ConditionalEliminator<storm::models::sparse::Dtmc<double>>;
template class ConditionalEliminator<double>;
#ifdef STORM_HAVE_CARL
template class ConditionalEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
template class ConditionalEliminator<storm::RationalFunction>;
#endif
} // namespace stateelimination

29
src/solver/stateelimination/ConditionalEliminator.h

@ -9,14 +9,11 @@ namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
class ConditionalEliminator : public StateEliminator<SparseModelType> {
typedef typename SparseModelType::ValueType ValueType;
enum SpecificState { NONE, PHI, PSI};
template<typename ValueType>
class ConditionalEliminator : public StateEliminator<ValueType> {
public:
enum class StateLabel { NONE, PHI, PSI };
ConditionalEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates);
// Instantiaton of Virtual methods
@ -26,24 +23,16 @@ namespace storm {
bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
bool isFilterPredecessor() const override;
void setStatePsi() {
specificState = PSI;
}
void setStatePhi() {
specificState = PHI;
}
void clearState() {
specificState = NONE;
}
void setFilterPhi();
void setFilterPsi();
void setFilter(StateLabel const& stateLabel);
void unsetFilter();
private:
std::vector<ValueType>& oneStepProbabilities;
storm::storage::BitVector& phiStates;
storm::storage::BitVector& psiStates;
SpecificState specificState;
StateLabel filterLabel;
};
} // namespace stateelimination

75
src/solver/stateelimination/DynamicStatePriorityQueue.cpp

@ -0,0 +1,75 @@
#include "src/solver/stateelimination/DynamicStatePriorityQueue.h"
#include "src/adapters/CarlAdapter.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename ValueType>
DynamicStatePriorityQueue<ValueType>::DynamicStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue(), transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions), oneStepProbabilities(oneStepProbabilities), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) {
// Insert all state-penalty pairs into our priority queue.
for (auto const& statePenalty : sortedStatePenaltyPairs) {
priorityQueue.insert(priorityQueue.end(), statePenalty);
}
// Insert all state-penalty pairs into auxiliary mapping.
for (auto const& statePenalty : sortedStatePenaltyPairs) {
stateToPriorityMapping.emplace(statePenalty);
}
}
template<typename ValueType>
bool DynamicStatePriorityQueue<ValueType>::hasNext() const {
return !priorityQueue.empty();
}
template<typename ValueType>
storm::storage::sparse::state_type DynamicStatePriorityQueue<ValueType>::pop() {
auto it = priorityQueue.begin();
STORM_LOG_TRACE("Popping state " << it->first << " with priority " << it->second << ".");
storm::storage::sparse::state_type result = it->first;
priorityQueue.erase(priorityQueue.begin());
return result;
}
template<typename ValueType>
void DynamicStatePriorityQueue<ValueType>::update(storm::storage::sparse::state_type state) {
// First, we need to find the priority until now.
auto priorityIt = stateToPriorityMapping.find(state);
// If the priority queue does not store the priority of the given state, we must not update it.
if (priorityIt == stateToPriorityMapping.end()) {
return;
}
uint_fast64_t lastPriority = priorityIt->second;
uint_fast64_t newPriority = penaltyFunction(state, transitionMatrix, backwardTransitions, oneStepProbabilities);
if (lastPriority != newPriority) {
// Erase and re-insert into the priority queue with the new priority.
auto queueIt = priorityQueue.find(std::make_pair(state, lastPriority));
priorityQueue.erase(queueIt);
priorityQueue.emplace(state, newPriority);
// Finally, update the probability in the mapping.
priorityIt->second = newPriority;
}
}
template<typename ValueType>
std::size_t DynamicStatePriorityQueue<ValueType>::size() const {
return priorityQueue.size();
}
template class DynamicStatePriorityQueue<double>;
#ifdef STORM_HAVE_CARL
template class DynamicStatePriorityQueue<storm::RationalFunction>;
#endif
}
}
}

48
src/solver/stateelimination/DynamicStatePriorityQueue.h

@ -0,0 +1,48 @@
#pragma once
#include <functional>
#include <vector>
#include <set>
#include <unordered_map>
#include "src/solver/stateelimination/StatePriorityQueue.h"
namespace storm {
namespace storage {
template<typename ValueType>
class FlexibleSparseMatrix;
}
namespace solver {
namespace stateelimination {
struct PriorityComparator {
bool operator()(std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& first, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& second) {
return (first.second < second.second) || (first.second == second.second && first.first < second.first) ;
}
};
template<typename ValueType>
class DynamicStatePriorityQueue : public StatePriorityQueue {
public:
typedef std::function<uint_fast64_t (storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities)> PenaltyFunctionType;
DynamicStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities, PenaltyFunctionType const& penaltyFunction);
virtual bool hasNext() const override;
virtual storm::storage::sparse::state_type pop() override;
virtual void update(storm::storage::sparse::state_type state) override;
virtual std::size_t size() const override;
private:
storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix;
storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions;
std::vector<ValueType> const& oneStepProbabilities;
std::set<std::pair<storm::storage::sparse::state_type, uint_fast64_t>, PriorityComparator> priorityQueue;
std::unordered_map<storm::storage::sparse::state_type, uint_fast64_t> stateToPriorityMapping;
PenaltyFunctionType penaltyFunction;
};
}
}
}

39
src/solver/stateelimination/LongRunAverageEliminator.cpp

@ -1,46 +1,31 @@
#include "src/solver/stateelimination/LongRunAverageEliminator.h"
#include "src/utility/constants.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
LongRunAverageEliminator<SparseModelType>::LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues, std::vector<ValueType>& averageTimeInStates) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues), averageTimeInStates(averageTimeInStates) {
template<typename ValueType>
LongRunAverageEliminator<ValueType>::LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues, std::vector<ValueType>& averageTimeInStates) : PrioritizedStateEliminator<ValueType>(transitionMatrix, backwardTransitions, priorityQueue, stateValues), averageTimeInStates(averageTimeInStates) {
}
template<typename SparseModelType>
void LongRunAverageEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]);
template<typename ValueType>
void LongRunAverageEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
this->stateValues[state] = storm::utility::simplify(loopProbability * this->stateValues[state]);
averageTimeInStates[state] = storm::utility::simplify(loopProbability * averageTimeInStates[state]);
}
template<typename SparseModelType>
void LongRunAverageEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state]));
template<typename ValueType>
void LongRunAverageEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
this->stateValues[predecessor] = storm::utility::simplify(this->stateValues[predecessor] + storm::utility::simplify(probability * this->stateValues[state]));
averageTimeInStates[predecessor] = storm::utility::simplify(averageTimeInStates[predecessor] + storm::utility::simplify(probability * averageTimeInStates[state]));
}
template<typename SparseModelType>
void LongRunAverageEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
priorityQueue->update(state, StateEliminator<SparseModelType>::transitionMatrix, StateEliminator<SparseModelType>::backwardTransitions, stateValues);
}
template<typename SparseModelType>
bool LongRunAverageEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
STORM_LOG_ASSERT(false, "Filter should not be applied.");
return false;
}
template<typename SparseModelType>
bool LongRunAverageEliminator<SparseModelType>::isFilterPredecessor() const {
return false;
}
template class LongRunAverageEliminator<storm::models::sparse::Dtmc<double>>;
template class LongRunAverageEliminator<double>;
#ifdef STORM_HAVE_CARL
template class LongRunAverageEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
template class LongRunAverageEliminator<storm::RationalFunction>;
#endif
} // namespace stateelimination

20
src/solver/stateelimination/LongRunAverageEliminator.h

@ -1,32 +1,26 @@
#ifndef STORM_SOLVER_STATEELIMINATION_LONGRUNAVERAGEELIMINATOR_H_
#define STORM_SOLVER_STATEELIMINATION_LONGRUNAVERAGEELIMINATOR_H_
#include "src/solver/stateelimination/StateEliminator.h"
#include "src/solver/stateelimination/PrioritizedStateEliminator.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
class LongRunAverageEliminator : public StateEliminator<SparseModelType> {
typedef typename SparseModelType::ValueType ValueType;
typedef typename std::shared_ptr<storm::modelchecker::StatePriorityQueue<ValueType>> PriorityQueuePointer;
class StatePriorityQueue;
template<typename ValueType>
class LongRunAverageEliminator : public PrioritizedStateEliminator<ValueType> {
public:
typedef typename std::shared_ptr<StatePriorityQueue> PriorityQueuePointer;
LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues, std::vector<ValueType>& averageTimeInStates);
// Instantiaton of Virtual methods
// Instantiaton of virtual methods.
void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
void updatePriority(storm::storage::sparse::state_type const& state) override;
bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
bool isFilterPredecessor() const override;
private:
PriorityQueuePointer priorityQueue;
std::vector<ValueType>& stateValues;
std::vector<ValueType>& averageTimeInStates;
};

46
src/solver/stateelimination/MAEliminator.cpp

@ -1,46 +0,0 @@
#include "src/solver/stateelimination/MAEliminator.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
MAEliminator<SparseModelType>::MAEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions){
}
template<typename SparseModelType>
void MAEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
// Do nothing
}
template<typename SparseModelType>
void MAEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
// Do nothing
}
template<typename SparseModelType>
void MAEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
// Do nothing
}
template<typename SparseModelType>
bool MAEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
STORM_LOG_ASSERT(false, "Filter should not be applied.");
return false;
}
template<typename SparseModelType>
bool MAEliminator<SparseModelType>::isFilterPredecessor() const {
return false;
}
template class MAEliminator<storm::models::sparse::Dtmc<double>>;
#ifdef STORM_HAVE_CARL
template class MAEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
#endif
} // namespace stateelimination
} // namespace storage
} // namespace storm

32
src/solver/stateelimination/MAEliminator.h

@ -1,32 +0,0 @@
#ifndef STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_
#define STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_
#include "src/solver/stateelimination/StateEliminator.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
class MAEliminator : public StateEliminator<SparseModelType> {
typedef typename SparseModelType::ValueType ValueType;
public:
MAEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions);
// Instantiaton of Virtual methods
void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
void updatePriority(storm::storage::sparse::state_type const& state) override;
bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
bool isFilterPredecessor() const override;
private:
};
} // namespace stateelimination
} // namespace storage
} // namespace storm
#endif // STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_

46
src/solver/stateelimination/PrioritizedEliminator.cpp

@ -1,46 +0,0 @@
#include "src/solver/stateelimination/PrioritizedEliminator.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
PrioritizedEliminator<SparseModelType>::PrioritizedEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues) {
}
template<typename SparseModelType>
void PrioritizedEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]);
}
template<typename SparseModelType>
void PrioritizedEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state]));
}
template<typename SparseModelType>
void PrioritizedEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
priorityQueue->update(state, StateEliminator<SparseModelType>::transitionMatrix, StateEliminator<SparseModelType>::backwardTransitions, stateValues);
}
template<typename SparseModelType>
bool PrioritizedEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
STORM_LOG_ASSERT(false, "Filter should not be applied.");
return false;
}
template<typename SparseModelType>
bool PrioritizedEliminator<SparseModelType>::isFilterPredecessor() const {
return false;
}
template class PrioritizedEliminator<storm::models::sparse::Dtmc<double>>;
#ifdef STORM_HAVE_CARL
template class PrioritizedEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
#endif
} // namespace stateelimination
} // namespace storage
} // namespace storm

35
src/solver/stateelimination/PrioritizedEliminator.h

@ -1,35 +0,0 @@
#ifndef STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_
#define STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_
#include "src/solver/stateelimination/StateEliminator.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
class PrioritizedEliminator : public StateEliminator<SparseModelType> {
typedef typename SparseModelType::ValueType ValueType;
typedef typename std::shared_ptr<storm::modelchecker::StatePriorityQueue<ValueType>> PriorityQueuePointer;
public:
PrioritizedEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues);
// Instantiaton of Virtual methods
void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
void updatePriority(storm::storage::sparse::state_type const& state) override;
bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
bool isFilterPredecessor() const override;
private:
PriorityQueuePointer priorityQueue;
std::vector<ValueType>& stateValues;
};
} // namespace stateelimination
} // namespace storage
} // namespace storm
#endif // STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_

39
src/solver/stateelimination/PrioritizedStateEliminator.cpp

@ -0,0 +1,39 @@
#include "src/solver/stateelimination/PrioritizedStateEliminator.h"
#include "src/solver/stateelimination/StatePriorityQueue.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename ValueType>
PrioritizedStateEliminator<ValueType>::PrioritizedStateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues) : StateEliminator<ValueType>(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues) {
}
template<typename ValueType>
void PrioritizedStateEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]);
}
template<typename ValueType>
void PrioritizedStateEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state]));
}
template<typename ValueType>
void PrioritizedStateEliminator<ValueType>::updatePriority(storm::storage::sparse::state_type const& state) {
priorityQueue->update(state);
}
template class PrioritizedStateEliminator<double>;
#ifdef STORM_HAVE_CARL
template class PrioritizedStateEliminator<storm::RationalFunction>;
#endif
} // namespace stateelimination
} // namespace storage
} // namespace storm

33
src/solver/stateelimination/PrioritizedStateEliminator.h

@ -0,0 +1,33 @@
#ifndef STORM_SOLVER_STATEELIMINATION_PRIORITIZEDSTATEELIMINATOR_H_
#define STORM_SOLVER_STATEELIMINATION_PRIORITIZEDSTATEELIMINATOR_H_
#include "src/solver/stateelimination/StateEliminator.h"
namespace storm {
namespace solver {
namespace stateelimination {
class StatePriorityQueue;
template<typename ValueType>
class PrioritizedStateEliminator : public StateEliminator<ValueType> {
public:
typedef typename std::shared_ptr<StatePriorityQueue> PriorityQueuePointer;
PrioritizedStateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues);
// Instantiaton of virtual methods.
void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
void updatePriority(storm::storage::sparse::state_type const& state) override;
protected:
PriorityQueuePointer priorityQueue;
std::vector<ValueType>& stateValues;
};
} // namespace stateelimination
} // namespace storage
} // namespace storm
#endif // STORM_SOLVER_STATEELIMINATION_PRIORITIZEDSTATEELIMINATOR_H_

64
src/solver/stateelimination/StateEliminator.cpp

@ -1,6 +1,11 @@
#include "src/solver/stateelimination/StateEliminator.h"
#include "src/adapters/CarlAdapter.h"
#include "src/storage/BitVector.h"
#include "src/utility/stateelimination.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidStateException.h"
@ -9,13 +14,15 @@ namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
StateEliminator<SparseModelType>::StateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) : transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions) {
}
using namespace storm::utility::stateelimination;
template<typename SparseModelType>
void StateEliminator<SparseModelType>::eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint) {
template<typename ValueType>
StateEliminator<ValueType>::StateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) : transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions) {
// Intentionally left empty.
}
template<typename ValueType>
void StateEliminator<ValueType>::eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint) {
STORM_LOG_TRACE("Eliminating state " << state << ".");
// Start by finding loop probability.
@ -124,7 +131,6 @@ namespace storm {
auto successorEntry = storm::utility::simplify(std::move(*first2 * multiplyFactor));
*result = successorEntry;
newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, successorEntry.getValue());
// std::cout << "(1) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
++first2;
++successorOffsetInNewBackwardTransitions;
} else if (first1->getColumn() < first2->getColumn()) {
@ -134,7 +140,6 @@ namespace storm {
auto probability = storm::utility::simplify(first1->getValue() + storm::utility::simplify(multiplyFactor * first2->getValue()));
*result = storm::storage::MatrixEntry<typename storm::storage::FlexibleSparseMatrix<ValueType>::index_type, typename storm::storage::FlexibleSparseMatrix<ValueType>::value_type>(first1->getColumn(), probability);
newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, probability);
// std::cout << "(2) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
++first1;
++first2;
++successorOffsetInNewBackwardTransitions;
@ -145,7 +150,6 @@ namespace storm {
auto stateProbability = storm::utility::simplify(std::move(*first2 * multiplyFactor));
*result = stateProbability;
newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, stateProbability.getValue());
// std::cout << "(3) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
++successorOffsetInNewBackwardTransitions;
}
}
@ -168,10 +172,6 @@ namespace storm {
}
FlexibleRowType& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn());
// std::cout << "old backward trans of " << successorEntry.getColumn() << std::endl;
// for (auto const& trans : successorBackwardTransitions) {
// std::cout << trans << std::endl;
// }
// Delete the current state as a predecessor of the successor state only if we are going to remove the
// current state's forward transitions.
@ -186,11 +186,6 @@ namespace storm {
FlexibleRowIterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin();
FlexibleRowIterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end();
// std::cout << "adding backward trans " << successorEntry.getColumn() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
// for (auto const& trans : newBackwardProbabilities[successorOffsetInNewBackwardTransitions]) {
// std::cout << trans << std::endl;
// }
FlexibleRowType newPredecessors;
newPredecessors.reserve((last1 - first1) + (last2 - first2));
std::insert_iterator<FlexibleRowType> result(newPredecessors, newPredecessors.end());
@ -206,7 +201,7 @@ namespace storm {
}
++first2;
} else if (first1->getColumn() == first2->getColumn()) {
if (storm::modelchecker::estimateComplexity(first1->getValue()) > storm::modelchecker::estimateComplexity(first2->getValue())) {
if (estimateComplexity(first1->getValue()) > estimateComplexity(first2->getValue())) {
*result = *first1;
} else {
*result = *first2;
@ -225,10 +220,6 @@ namespace storm {
}
// Now move the new predecessors in place.
successorBackwardTransitions = std::move(newPredecessors);
// std::cout << "new backward trans of " << successorEntry.getColumn() << std::endl;
// for (auto const& trans : successorBackwardTransitions) {
// std::cout << trans << std::endl;
// }
++successorOffsetInNewBackwardTransitions;
}
STORM_LOG_TRACE("Fixed predecessor lists of successor states.");
@ -244,13 +235,38 @@ namespace storm {
currentStatePredecessors.clear();
currentStatePredecessors.shrink_to_fit();
}
}
template<typename ValueType>
void StateEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
// Intentionally left empty.
}
template<typename ValueType>
void StateEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
// Intentionally left empty.
}
template<typename ValueType>
void StateEliminator<ValueType>::updatePriority(storm::storage::sparse::state_type const& state) {
// Intentionally left empty.
}
template<typename ValueType>
bool StateEliminator<ValueType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
STORM_LOG_ASSERT(false, "Must not filter predecessors.");
return false;
}
template<typename ValueType>
bool StateEliminator<ValueType>::isFilterPredecessor() const {
return false;
}
template class StateEliminator<storm::models::sparse::Dtmc<double>>;
template class StateEliminator<double>;
#ifdef STORM_HAVE_CARL
template class StateEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
template class StateEliminator<storm::RationalFunction>;
#endif
} // namespace stateelimination

29
src/solver/stateelimination/StateEliminator.h

@ -1,42 +1,35 @@
#ifndef STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_
#define STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_
#include "src/storage/FlexibleSparseMatrix.h"
#include "src/storage/SparseMatrix.h"
#include "src/storage/sparse/StateType.h"
#include "src/models/sparse/Dtmc.h"
#include "src/models/sparse/StandardRewardModel.h"
#include "src/adapters/CarlAdapter.h"
#include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h"
#include "src/utility/macros.h"
#include "src/storage/FlexibleSparseMatrix.h"
#include "src/storage/BitVector.h"
namespace storm {
namespace solver {
namespace stateelimination {
template<typename SparseModelType>
template<typename ValueType>
class StateEliminator {
typedef typename SparseModelType::ValueType ValueType;
public:
typedef typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type FlexibleRowType;
typedef typename FlexibleRowType::iterator FlexibleRowIterator;
public:
StateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions);
void eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint = storm::storage::BitVector());
// Virtual methods for base classes to distinguish between different state elimination approaches
virtual void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) = 0;
virtual void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) = 0;
virtual void updatePriority(storm::storage::sparse::state_type const& state) = 0;
virtual bool filterPredecessor(storm::storage::sparse::state_type const& state) = 0;
virtual bool isFilterPredecessor() const = 0;
// Provide virtual methods that can be customized by subclasses to govern side-effect of the elimination.
virtual void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability);
virtual void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state);
virtual void updatePriority(storm::storage::sparse::state_type const& state);
virtual bool filterPredecessor(storm::storage::sparse::state_type const& state);
virtual bool isFilterPredecessor() const;
protected:
storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix;
storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions;
};
} // namespace stateelimination

13
src/solver/stateelimination/StatePriorityQueue.cpp

@ -0,0 +1,13 @@
#include "src/solver/stateelimination/StatePriorityQueue.h"
namespace storm {
namespace solver {
namespace stateelimination {
void StatePriorityQueue::update(storm::storage::sparse::state_type state) {
// Intentionally left empty.
}
}
}
}

21
src/solver/stateelimination/StatePriorityQueue.h

@ -0,0 +1,21 @@
#pragma once
#include <cstddef>
#include "src/storage/sparse/StateType.h"
namespace storm {
namespace solver {
namespace stateelimination {
class StatePriorityQueue {
public:
virtual bool hasNext() const = 0;
virtual storm::storage::sparse::state_type pop() = 0;
virtual void update(storm::storage::sparse::state_type state);
virtual std::size_t size() const = 0;
};
}
}
}

28
src/solver/stateelimination/StaticStatePriorityQueue.cpp

@ -0,0 +1,28 @@
#include "src/solver/stateelimination/StaticStatePriorityQueue.h"
#include "src/adapters/CarlAdapter.h"
namespace storm {
namespace solver {
namespace stateelimination {
StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates) : StatePriorityQueue(), sortedStates(sortedStates), currentPosition(0) {
// Intentionally left empty.
}
bool StaticStatePriorityQueue::hasNext() const {
return currentPosition < sortedStates.size();
}
storm::storage::sparse::state_type StaticStatePriorityQueue::pop() {
++currentPosition;
return sortedStates[currentPosition - 1];
}
std::size_t StaticStatePriorityQueue::size() const {
return sortedStates.size() - currentPosition;
}
}
}
}

26
src/solver/stateelimination/StaticStatePriorityQueue.h

@ -0,0 +1,26 @@
#pragma once
#include <vector>
#include "src/solver/stateelimination/StatePriorityQueue.h"
namespace storm {
namespace solver {
namespace stateelimination {
class StaticStatePriorityQueue : public StatePriorityQueue {
public:
StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates);
virtual bool hasNext() const override;
virtual storm::storage::sparse::state_type pop() override;
virtual std::size_t size() const override;
private:
std::vector<uint_fast64_t> sortedStates;
uint_fast64_t currentPosition;
};
}
}
}

160
src/utility/stateelimination.cpp

@ -0,0 +1,160 @@
#include "src/utility/stateelimination.h"
#include <random>
#include "src/solver/stateelimination/StatePriorityQueue.h"
#include "src/solver/stateelimination/StaticStatePriorityQueue.h"
#include "src/solver/stateelimination/DynamicStatePriorityQueue.h"
#include "src/storage/BitVector.h"
#include "src/storage/FlexibleSparseMatrix.h"
#include "src/settings/SettingsManager.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
#include "src/exceptions/InvalidStateException.h"
#include "src/exceptions/InvalidSettingsException.h"
namespace storm {
namespace utility {
namespace stateelimination {
bool eliminationOrderNeedsDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Backward ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
}
bool eliminationOrderNeedsForwardDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed;
}
bool eliminationOrderNeedsReversedDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
}
bool eliminationOrderIsPenaltyBased(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::DynamicPenalty ||
order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression;
}
bool eliminationOrderIsStatic(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
return eliminationOrderNeedsDistances(order) || order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty;
}
template<typename ValueType>
uint_fast64_t estimateComplexity(ValueType const& value) {
return 1;
}
#ifdef STORM_HAVE_CARL
template<>
uint_fast64_t estimateComplexity(storm::RationalFunction const& value) {
if (storm::utility::isConstant(value)) {
return 1;
}
if (value.denominator().isConstant()) {
return value.nominator().complexity();
} else {
return value.denominator().complexity() * value.nominator().complexity();
}
}
#endif
template<typename ValueType>
uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
uint_fast64_t penalty = 0;
bool hasParametricSelfLoop = false;
for (auto const& predecessor : backwardTransitions.getRow(state)) {
for (auto const& successor : transitionMatrix.getRow(state)) {
penalty += estimateComplexity(predecessor.getValue()) * estimateComplexity(successor.getValue());
}
if (predecessor.getColumn() == state) {
hasParametricSelfLoop = !storm::utility::isConstant(predecessor.getValue());
}
penalty += estimateComplexity(oneStepProbabilities[predecessor.getColumn()]) * estimateComplexity(predecessor.getValue()) * estimateComplexity(oneStepProbabilities[state]);
}
// If it is a self-loop that is parametric, we increase the penalty a lot.
if (hasParametricSelfLoop) {
penalty *= 10;
}
return penalty;
}
template<typename ValueType>
uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
return backwardTransitions.getRow(state).size() * transitionMatrix.getRow(state).size();
}
template<typename ValueType>
std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states) {
STORM_LOG_TRACE("Creating state priority queue for states " << states);
// Get the settings to customize the priority queue.
storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
if (order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Random) {
std::random_device randomDevice;
std::mt19937 generator(randomDevice());
std::shuffle(sortedStates.begin(), sortedStates.end(), generator);
return std::make_unique<StaticStatePriorityQueue>(sortedStates);
} else {
if (eliminationOrderNeedsDistances(order)) {
STORM_LOG_THROW(static_cast<bool>(distanceBasedStatePriorities), storm::exceptions::InvalidStateException, "Unable to build state priority queue without distance-based priorities.");
std::sort(sortedStates.begin(), sortedStates.end(), [&distanceBasedStatePriorities] (storm::storage::sparse::state_type const& state1, storm::storage::sparse::state_type const& state2) { return distanceBasedStatePriorities.get()[state1] < distanceBasedStatePriorities.get()[state2]; } );
return std::make_unique<StaticStatePriorityQueue>(sortedStates);
} else if (eliminationOrderIsPenaltyBased(order)) {
std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> statePenalties(sortedStates.size());
typename DynamicStatePriorityQueue<ValueType>::PenaltyFunctionType penaltyFunction = order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression ? computeStatePenaltyRegularExpression<ValueType> : computeStatePenalty<ValueType>;
for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
statePenalties[index] = std::make_pair(sortedStates[index], penaltyFunction(sortedStates[index], transitionMatrix, backwardTransitions, oneStepProbabilities));
}
std::sort(statePenalties.begin(), statePenalties.end(), [] (std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty1, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty2) { return statePenalty1.second < statePenalty2.second; } );
if (eliminationOrderIsStatic(order)) {
// For the static penalty version, we need to strip the penalties to create the queue.
for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
sortedStates[index] = statePenalties[index].first;
}
return std::make_unique<StaticStatePriorityQueue>(sortedStates);
} else {
// For the dynamic penalty version, we need to give the full state-penalty pairs.
return std::make_unique<DynamicStatePriorityQueue<ValueType>>(statePenalties, transitionMatrix, backwardTransitions, oneStepProbabilities, penaltyFunction);
}
}
}
STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Illegal elimination order selected.");
}
std::shared_ptr<StatePriorityQueue> createNaivePriorityQueue(storm::storage::BitVector const& states) {
std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
return std::make_shared<StaticStatePriorityQueue>(sortedStates);
}
template uint_fast64_t estimateComplexity(double const& value);
template std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<double> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<double> const& backwardTransitions, std::vector<double>& oneStepProbabilities, storm::storage::BitVector const& states);
template uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<double> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<double> const& backwardTransitions, std::vector<double> const& oneStepProbabilities);
template uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<double> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<double> const& backwardTransitions, std::vector<double> const& oneStepProbabilities);
#ifdef STORM_HAVE_CARL
template uint_fast64_t estimateComplexity(storm::RationalFunction const& value);
template std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& backwardTransitions, std::vector<storm::RationalFunction>& oneStepProbabilities, storm::storage::BitVector const& states);
template uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& backwardTransitions, std::vector<storm::RationalFunction> const& oneStepProbabilities);
template uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& backwardTransitions, std::vector<storm::RationalFunction> const& oneStepProbabilities);
#endif
}
}
}

60
src/utility/stateelimination.h

@ -0,0 +1,60 @@
#pragma once
#include <memory>
#include <vector>
#include <boost/optional.hpp>
#include "src/storage/sparse/StateType.h"
#include "src/adapters/CarlAdapter.h"
#include "src/settings/modules/SparseDtmcEliminationModelCheckerSettings.h"
namespace storm {
namespace solver {
namespace stateelimination {
class StatePriorityQueue;
}
}
namespace storage {
class BitVector;
template<typename ValueType>
class FlexibleSparseMatrix;
}
namespace utility {
namespace stateelimination {
using namespace storm::solver::stateelimination;
bool eliminationOrderNeedsDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
bool eliminationOrderNeedsForwardDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
bool eliminationOrderNeedsReversedDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
bool eliminationOrderIsPenaltyBased(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
bool eliminationOrderIsStatic(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
template<typename ValueType>
uint_fast64_t estimateComplexity(ValueType const& value);
#ifdef STORM_HAVE_CARL
template<>
uint_fast64_t estimateComplexity(storm::RationalFunction const& value);
#endif
template<typename ValueType>
uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
template<typename ValueType>
uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
template<typename ValueType>
std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& stateDistances, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states);
std::shared_ptr<StatePriorityQueue> createNaivePriorityQueue(storm::storage::BitVector const& states);
}
}
}
Loading…
Cancel
Save