|
@ -96,9 +96,9 @@ namespace storm { |
|
|
// Determine the states that have 0 probability of reaching the target states. |
|
|
// Determine the states that have 0 probability of reaching the target states. |
|
|
storm::storage::BitVector statesWithProbabilityGreater0; |
|
|
storm::storage::BitVector statesWithProbabilityGreater0; |
|
|
if (this->minimumOperatorStack.top()) { |
|
|
if (this->minimumOperatorStack.top()) { |
|
|
statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0A(this->getModel(), this->getModel().getBackwardTransitions(), phiStates, psiStates, true, stepBound); |
|
|
|
|
|
|
|
|
statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0A(this->getModel().getTransitionMatrix(), this->getModel().getNondeterministicChoiceIndices(), this->getModel().getBackwardTransitions(), phiStates, psiStates, true, stepBound); |
|
|
} else { |
|
|
} else { |
|
|
statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0E(this->getModel(), this->getModel().getBackwardTransitions(), phiStates, psiStates, true, stepBound); |
|
|
|
|
|
|
|
|
statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0E(this->getModel().getTransitionMatrix(), this->getModel().getNondeterministicChoiceIndices(), this->getModel().getBackwardTransitions(), phiStates, psiStates, true, stepBound); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Check if we already know the result (i.e. probability 0) for all initial states and |
|
|
// Check if we already know the result (i.e. probability 0) for all initial states and |
|
@ -278,29 +278,30 @@ namespace storm { |
|
|
* @return The probabilities for the satisfying phi until psi for each state of the model. If the |
|
|
* @return The probabilities for the satisfying phi until psi for each state of the model. If the |
|
|
* qualitative flag is set, exact probabilities might not be computed. |
|
|
* qualitative flag is set, exact probabilities might not be computed. |
|
|
*/ |
|
|
*/ |
|
|
std::pair<std::vector<Type>, storm::storage::TotalScheduler> checkUntil(bool minimize, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative) const { |
|
|
|
|
|
|
|
|
static std::pair<std::vector<Type>, storm::storage::TotalScheduler> computeUnboundedUntilProbabilities(bool minimize, storm::storage::SparseMatrix<Type> const& transitionMatrix, std::vector<uint_fast64_t> nondeterministicChoiceIndices, storm::storage::SparseMatrix<Type> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<Type>> nondeterministicLinearEquationSolver, bool qualitative) { |
|
|
|
|
|
size_t numberOfStates = phiStates.size(); |
|
|
|
|
|
|
|
|
// We need to identify the states which have to be taken out of the matrix, i.e. |
|
|
// We need to identify the states which have to be taken out of the matrix, i.e. |
|
|
// all states that have probability 0 and 1 of satisfying the until-formula. |
|
|
// all states that have probability 0 and 1 of satisfying the until-formula. |
|
|
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01; |
|
|
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01; |
|
|
if (minimize) { |
|
|
if (minimize) { |
|
|
statesWithProbability01 = storm::utility::graph::performProb01Min(this->getModel(), phiStates, psiStates); |
|
|
|
|
|
|
|
|
statesWithProbability01 = storm::utility::graph::performProb01Min(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates); |
|
|
} else { |
|
|
} else { |
|
|
statesWithProbability01 = storm::utility::graph::performProb01Max(this->getModel(), phiStates, psiStates); |
|
|
|
|
|
|
|
|
statesWithProbability01 = storm::utility::graph::performProb01Max(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates); |
|
|
} |
|
|
} |
|
|
storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first); |
|
|
storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first); |
|
|
storm::storage::BitVector statesWithProbability1 = std::move(statesWithProbability01.second); |
|
|
storm::storage::BitVector statesWithProbability1 = std::move(statesWithProbability01.second); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
storm::storage::BitVector maybeStates = ~(statesWithProbability0 | statesWithProbability1); |
|
|
storm::storage::BitVector maybeStates = ~(statesWithProbability0 | statesWithProbability1); |
|
|
LOG4CPLUS_INFO(logger, "Found " << statesWithProbability0.getNumberOfSetBits() << " 'no' states."); |
|
|
LOG4CPLUS_INFO(logger, "Found " << statesWithProbability0.getNumberOfSetBits() << " 'no' states."); |
|
|
LOG4CPLUS_INFO(logger, "Found " << statesWithProbability1.getNumberOfSetBits() << " 'yes' states."); |
|
|
LOG4CPLUS_INFO(logger, "Found " << statesWithProbability1.getNumberOfSetBits() << " 'yes' states."); |
|
|
LOG4CPLUS_INFO(logger, "Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); |
|
|
LOG4CPLUS_INFO(logger, "Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); |
|
|
|
|
|
|
|
|
// Create resulting vector. |
|
|
// Create resulting vector. |
|
|
std::vector<Type> result(this->getModel().getNumberOfStates()); |
|
|
|
|
|
|
|
|
std::vector<Type> result(numberOfStates); |
|
|
|
|
|
|
|
|
// Check whether we need to compute exact probabilities for some states. |
|
|
// Check whether we need to compute exact probabilities for some states. |
|
|
if (this->getModel().getInitialStates().isDisjointFrom(maybeStates) || qualitative) { |
|
|
|
|
|
|
|
|
if (initialStates.isDisjointFrom(maybeStates) || qualitative) { |
|
|
if (qualitative) { |
|
|
if (qualitative) { |
|
|
LOG4CPLUS_INFO(logger, "The formula was checked qualitatively. No exact probabilities were computed."); |
|
|
LOG4CPLUS_INFO(logger, "The formula was checked qualitatively. No exact probabilities were computed."); |
|
|
} else { |
|
|
} else { |
|
@ -315,20 +316,20 @@ namespace storm { |
|
|
|
|
|
|
|
|
// First, we can eliminate the rows and columns from the original transition probability matrix for states |
|
|
// First, we can eliminate the rows and columns from the original transition probability matrix for states |
|
|
// whose probabilities are already known. |
|
|
// whose probabilities are already known. |
|
|
storm::storage::SparseMatrix<Type> submatrix = this->getModel().getTransitionMatrix().getSubmatrix(maybeStates, this->getModel().getNondeterministicChoiceIndices()); |
|
|
|
|
|
|
|
|
storm::storage::SparseMatrix<Type> submatrix = transitionMatrix.getSubmatrix(maybeStates, nondeterministicChoiceIndices); |
|
|
|
|
|
|
|
|
// Get the "new" nondeterministic choice indices for the submatrix. |
|
|
// Get the "new" nondeterministic choice indices for the submatrix. |
|
|
std::vector<uint_fast64_t> subNondeterministicChoiceIndices = storm::utility::vector::getConstrainedOffsetVector(this->getModel().getNondeterministicChoiceIndices(), maybeStates); |
|
|
|
|
|
|
|
|
std::vector<uint_fast64_t> subNondeterministicChoiceIndices = storm::utility::vector::getConstrainedOffsetVector(nondeterministicChoiceIndices, maybeStates); |
|
|
|
|
|
|
|
|
// Prepare the right-hand side of the equation system. For entry i this corresponds to |
|
|
// Prepare the right-hand side of the equation system. For entry i this corresponds to |
|
|
// the accumulated probability of going from state i to some 'yes' state. |
|
|
// the accumulated probability of going from state i to some 'yes' state. |
|
|
std::vector<Type> b = this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, this->getModel().getNondeterministicChoiceIndices(), statesWithProbability1, submatrix.getRowCount()); |
|
|
|
|
|
|
|
|
std::vector<Type> b = transitionMatrix.getConstrainedRowSumVector(maybeStates, nondeterministicChoiceIndices, statesWithProbability1, submatrix.getRowCount()); |
|
|
|
|
|
|
|
|
// Create vector for results for maybe states. |
|
|
// Create vector for results for maybe states. |
|
|
std::vector<Type> x(maybeStates.getNumberOfSetBits()); |
|
|
std::vector<Type> x(maybeStates.getNumberOfSetBits()); |
|
|
|
|
|
|
|
|
// Solve the corresponding system of equations. |
|
|
// Solve the corresponding system of equations. |
|
|
this->nondeterministicLinearEquationSolver->solveEquationSystem(minimize, submatrix, x, b, subNondeterministicChoiceIndices); |
|
|
|
|
|
|
|
|
nondeterministicLinearEquationSolver->solveEquationSystem(minimize, submatrix, x, b, subNondeterministicChoiceIndices); |
|
|
|
|
|
|
|
|
// Set values of resulting vector according to result. |
|
|
// Set values of resulting vector according to result. |
|
|
storm::utility::vector::setVectorValues<Type>(result, maybeStates, x); |
|
|
storm::utility::vector::setVectorValues<Type>(result, maybeStates, x); |
|
@ -339,11 +340,15 @@ namespace storm { |
|
|
storm::utility::vector::setVectorValues<Type>(result, statesWithProbability1, storm::utility::constGetOne<Type>()); |
|
|
storm::utility::vector::setVectorValues<Type>(result, statesWithProbability1, storm::utility::constGetOne<Type>()); |
|
|
|
|
|
|
|
|
// Finally, compute a scheduler that achieves the extramal value. |
|
|
// Finally, compute a scheduler that achieves the extramal value. |
|
|
storm::storage::TotalScheduler scheduler = this->computeExtremalScheduler(minimize, false, result); |
|
|
|
|
|
|
|
|
storm::storage::TotalScheduler scheduler = computeExtremalScheduler(minimize, transitionMatrix, nondeterministicChoiceIndices, result); |
|
|
|
|
|
|
|
|
return std::make_pair(result, scheduler); |
|
|
return std::make_pair(result, scheduler); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::pair<std::vector<Type>, storm::storage::TotalScheduler> checkUntil(bool minimize, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative) const { |
|
|
|
|
|
return computeUnboundedUntilProbabilities(minimize, this->getModel().getTransitionMatrix(), this->getModel().getNondeterministicChoiceIndices(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, this->nondeterministicLinearEquationSolver, qualitative); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/*! |
|
|
/*! |
|
|
* Checks the given formula that is an instantaneous reward formula. |
|
|
* Checks the given formula that is an instantaneous reward formula. |
|
|
* |
|
|
* |
|
@ -453,9 +458,9 @@ namespace storm { |
|
|
storm::storage::BitVector infinityStates; |
|
|
storm::storage::BitVector infinityStates; |
|
|
storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); |
|
|
storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); |
|
|
if (minimize) { |
|
|
if (minimize) { |
|
|
infinityStates = std::move(storm::utility::graph::performProb1A(this->getModel(), this->getModel().getBackwardTransitions(), trueStates, targetStates)); |
|
|
|
|
|
|
|
|
infinityStates = std::move(storm::utility::graph::performProb1A(this->getModel().getTransitionMatrix(), this->getModel().getNondeterministicChoiceIndices(), this->getModel().getBackwardTransitions(), trueStates, targetStates)); |
|
|
} else { |
|
|
} else { |
|
|
infinityStates = std::move(storm::utility::graph::performProb1E(this->getModel(), this->getModel().getBackwardTransitions(), trueStates, targetStates)); |
|
|
|
|
|
|
|
|
infinityStates = std::move(storm::utility::graph::performProb1E(this->getModel().getTransitionMatrix(), this->getModel().getNondeterministicChoiceIndices(), this->getModel().getBackwardTransitions(), trueStates, targetStates)); |
|
|
} |
|
|
} |
|
|
infinityStates.complement(); |
|
|
infinityStates.complement(); |
|
|
storm::storage::BitVector maybeStates = ~targetStates & ~infinityStates; |
|
|
storm::storage::BitVector maybeStates = ~targetStates & ~infinityStates; |
|
@ -526,7 +531,7 @@ namespace storm { |
|
|
storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::constGetInfinity<Type>()); |
|
|
storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::constGetInfinity<Type>()); |
|
|
|
|
|
|
|
|
// Finally, compute a scheduler that achieves the extramal value. |
|
|
// Finally, compute a scheduler that achieves the extramal value. |
|
|
storm::storage::TotalScheduler scheduler = this->computeExtremalScheduler(this->minimumOperatorStack.top(), false, result); |
|
|
|
|
|
|
|
|
storm::storage::TotalScheduler scheduler = computeExtremalScheduler(this->minimumOperatorStack.top(), this->getModel().getTransitionMatrix(), this->getModel().getNondeterministicChoiceIndices(), result, this->getModel().hasStateRewards() ? &this->getModel().getStateRewardVector() : nullptr, this->getModel().hasTransitionRewards() ? &this->getModel().getTransitionRewardMatrix() : nullptr); |
|
|
|
|
|
|
|
|
return std::make_pair(result, scheduler); |
|
|
return std::make_pair(result, scheduler); |
|
|
} |
|
|
} |
|
@ -540,33 +545,33 @@ namespace storm { |
|
|
* @param takenChoices The output vector that is to store the taken choices. |
|
|
* @param takenChoices The output vector that is to store the taken choices. |
|
|
* @param nondeterministicChoiceIndices The assignment of states to their nondeterministic choices in the matrix. |
|
|
* @param nondeterministicChoiceIndices The assignment of states to their nondeterministic choices in the matrix. |
|
|
*/ |
|
|
*/ |
|
|
storm::storage::TotalScheduler computeExtremalScheduler(bool minimize, bool addRewards, std::vector<Type> const& result) const { |
|
|
|
|
|
std::vector<Type> temporaryResult(this->getModel().getNondeterministicChoiceIndices().size() - 1); |
|
|
|
|
|
|
|
|
static storm::storage::TotalScheduler computeExtremalScheduler(bool minimize, storm::storage::SparseMatrix<Type> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<Type> const& result, std::vector<Type> const* stateRewardVector = nullptr, storm::storage::SparseMatrix<Type> const* transitionRewardMatrix = nullptr) { |
|
|
|
|
|
std::vector<Type> temporaryResult(nondeterministicChoiceIndices.size() - 1); |
|
|
std::vector<Type> nondeterministicResult(result); |
|
|
std::vector<Type> nondeterministicResult(result); |
|
|
storm::solver::GmmxxLinearEquationSolver<Type> solver; |
|
|
storm::solver::GmmxxLinearEquationSolver<Type> solver; |
|
|
solver.performMatrixVectorMultiplication(this->getModel().getTransitionMatrix(), nondeterministicResult, nullptr, 1); |
|
|
|
|
|
if (addRewards) { |
|
|
|
|
|
|
|
|
solver.performMatrixVectorMultiplication(transitionMatrix, nondeterministicResult, nullptr, 1); |
|
|
|
|
|
if (stateRewardVector != nullptr || transitionRewardMatrix != nullptr) { |
|
|
std::vector<Type> totalRewardVector; |
|
|
std::vector<Type> totalRewardVector; |
|
|
if (this->getModel().hasTransitionRewards()) { |
|
|
|
|
|
std::vector<Type> totalRewardVector = this->getModel().getTransitionMatrix().getPointwiseProductRowSumVector(this->getModel().getTransitionRewardMatrix()); |
|
|
|
|
|
if (this->getModel().hasStateRewards()) { |
|
|
|
|
|
|
|
|
if (transitionRewardMatrix != nullptr) { |
|
|
|
|
|
totalRewardVector = transitionMatrix.getPointwiseProductRowSumVector(*transitionRewardMatrix); |
|
|
|
|
|
if (stateRewardVector != nullptr) { |
|
|
std::vector<Type> stateRewards(totalRewardVector.size()); |
|
|
std::vector<Type> stateRewards(totalRewardVector.size()); |
|
|
storm::utility::vector::selectVectorValuesRepeatedly(stateRewards, storm::storage::BitVector(this->getModel().getStateRewardVector().size(), true), this->getModel().getNondeterministicChoiceIndices(), this->getModel().getStateRewardVector()); |
|
|
|
|
|
|
|
|
storm::utility::vector::selectVectorValuesRepeatedly(stateRewards, storm::storage::BitVector(stateRewardVector->size(), true), nondeterministicChoiceIndices, *stateRewardVector); |
|
|
storm::utility::vector::addVectorsInPlace(totalRewardVector, stateRewards); |
|
|
storm::utility::vector::addVectorsInPlace(totalRewardVector, stateRewards); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
totalRewardVector.resize(nondeterministicResult.size()); |
|
|
totalRewardVector.resize(nondeterministicResult.size()); |
|
|
storm::utility::vector::selectVectorValuesRepeatedly(totalRewardVector, storm::storage::BitVector(this->getModel().getStateRewardVector().size(), true), this->getModel().getNondeterministicChoiceIndices(), this->getModel().getStateRewardVector()); |
|
|
|
|
|
|
|
|
storm::utility::vector::selectVectorValuesRepeatedly(totalRewardVector, storm::storage::BitVector(stateRewardVector->size(), true), nondeterministicChoiceIndices, *stateRewardVector); |
|
|
} |
|
|
} |
|
|
storm::utility::vector::addVectorsInPlace(nondeterministicResult, totalRewardVector); |
|
|
storm::utility::vector::addVectorsInPlace(nondeterministicResult, totalRewardVector); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<uint_fast64_t> choices(this->getModel().getNumberOfStates()); |
|
|
|
|
|
|
|
|
std::vector<uint_fast64_t> choices(result.size()); |
|
|
|
|
|
|
|
|
if (minimize) { |
|
|
if (minimize) { |
|
|
storm::utility::vector::reduceVectorMin(nondeterministicResult, temporaryResult, this->getModel().getNondeterministicChoiceIndices(), &choices); |
|
|
|
|
|
|
|
|
storm::utility::vector::reduceVectorMin(nondeterministicResult, temporaryResult, nondeterministicChoiceIndices, &choices); |
|
|
} else { |
|
|
} else { |
|
|
storm::utility::vector::reduceVectorMax(nondeterministicResult, temporaryResult, this->getModel().getNondeterministicChoiceIndices(), &choices); |
|
|
|
|
|
|
|
|
storm::utility::vector::reduceVectorMax(nondeterministicResult, temporaryResult, nondeterministicChoiceIndices, &choices); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return storm::storage::TotalScheduler(choices); |
|
|
return storm::storage::TotalScheduler(choices); |
|
|