Matthias Volk
5 years ago
10 changed files with 194 additions and 195 deletions
-
13src/storm-cli-utilities/model-handling.h
-
125src/storm-counterexamples/counterexamples/GuaranteedLabelSet.h
-
3src/storm-counterexamples/counterexamples/HighLevelCounterexample.h
-
22src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h
-
16src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h
-
34src/storm-counterexamples/settings/modules/CounterexampleGeneratorSettings.cpp
-
23src/storm-counterexamples/settings/modules/CounterexampleGeneratorSettings.h
-
8src/storm/settings/modules/CoreSettings.cpp
-
17src/storm/settings/modules/CoreSettings.h
-
128src/storm/utility/counterexamples.h
@ -0,0 +1,125 @@ |
|||
#pragma once |
|||
|
|||
#include <queue> |
|||
#include <utility> |
|||
|
|||
#include "storm/exceptions/InvalidArgumentException.h" |
|||
#include "storm/models/sparse/Model.h" |
|||
#include "storm/storage/sparse/PrismChoiceOrigins.h" |
|||
|
|||
namespace storm { |
|||
namespace counterexamples { |
|||
|
|||
/*! |
|||
* Computes a set of labels that is executed along all paths from any state to a target state. |
|||
* |
|||
* @param labelSet the considered label sets (a label set is assigned to each choice) |
|||
* |
|||
* @return The set of labels that is visited on all paths from any state to a target state. |
|||
*/ |
|||
template<typename T> |
|||
std::vector<storm::storage::FlatSet<uint_fast64_t>> getGuaranteedLabelSets(storm::models::sparse::Model<T> const& model, std::vector<storm::storage::FlatSet<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, storm::storage::FlatSet<uint_fast64_t> const& relevantLabels) { |
|||
STORM_LOG_THROW(model.getNumberOfChoices() == labelSets.size(), storm::exceptions::InvalidArgumentException, "The given number of labels does not match the number of choices."); |
|||
|
|||
// Get some data from the model for convenient access. |
|||
storm::storage::SparseMatrix<T> const& transitionMatrix = model.getTransitionMatrix(); |
|||
std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices(); |
|||
storm::storage::SparseMatrix<T> backwardTransitions = model.getBackwardTransitions(); |
|||
|
|||
// Now we compute the set of labels that is present on all paths from the initial to the target states. |
|||
std::vector<storm::storage::FlatSet<uint_fast64_t>> analysisInformation(model.getNumberOfStates(), relevantLabels); |
|||
|
|||
std::queue<uint_fast64_t> worklist; |
|||
storm::storage::BitVector statesInWorkList(model.getNumberOfStates()); |
|||
storm::storage::BitVector markedStates(model.getNumberOfStates()); |
|||
|
|||
// Initially, put all predecessors of target states in the worklist and empty the analysis information them. |
|||
for (auto state : psiStates) { |
|||
analysisInformation[state] = storm::storage::FlatSet<uint_fast64_t>(); |
|||
for (auto const& predecessorEntry : backwardTransitions.getRow(state)) { |
|||
if (predecessorEntry.getColumn() != state && !statesInWorkList.get(predecessorEntry.getColumn()) && !psiStates.get(predecessorEntry.getColumn())) { |
|||
worklist.push(predecessorEntry.getColumn()); |
|||
statesInWorkList.set(predecessorEntry.getColumn()); |
|||
markedStates.set(state); |
|||
} |
|||
} |
|||
} |
|||
|
|||
uint_fast64_t iters = 0; |
|||
while (!worklist.empty()) { |
|||
++iters; |
|||
uint_fast64_t const& currentState = worklist.front(); |
|||
|
|||
size_t analysisInformationSizeBefore = analysisInformation[currentState].size(); |
|||
|
|||
// Iterate over the successor states for all choices and compute new analysis information. |
|||
for (uint_fast64_t currentChoice = nondeterministicChoiceIndices[currentState]; currentChoice < nondeterministicChoiceIndices[currentState + 1]; ++currentChoice) { |
|||
bool modifiedChoice = false; |
|||
|
|||
for (auto const& entry : transitionMatrix.getRow(currentChoice)) { |
|||
if (markedStates.get(entry.getColumn())) { |
|||
modifiedChoice = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
// If we can reach the target state with this choice, we need to intersect the current |
|||
// analysis information with the union of the new analysis information of the target state |
|||
// and the choice labels. |
|||
if (modifiedChoice) { |
|||
for (auto const& entry : transitionMatrix.getRow(currentChoice)) { |
|||
if (markedStates.get(entry.getColumn())) { |
|||
storm::storage::FlatSet<uint_fast64_t> tmpIntersection; |
|||
std::set_intersection(analysisInformation[currentState].begin(), analysisInformation[currentState].end(), analysisInformation[entry.getColumn()].begin(), analysisInformation[entry.getColumn()].end(), std::inserter(tmpIntersection, tmpIntersection.begin())); |
|||
std::set_intersection(analysisInformation[currentState].begin(), analysisInformation[currentState].end(), labelSets[currentChoice].begin(), labelSets[currentChoice].end(), std::inserter(tmpIntersection, tmpIntersection.begin())); |
|||
analysisInformation[currentState] = std::move(tmpIntersection); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// If the analysis information changed, we need to update it and put all the predecessors of this |
|||
// state in the worklist. |
|||
if (analysisInformation[currentState].size() != analysisInformationSizeBefore) { |
|||
for (auto const& predecessorEntry : backwardTransitions.getRow(currentState)) { |
|||
// Only put the predecessor in the worklist if it's not already a target state. |
|||
if (!psiStates.get(predecessorEntry.getColumn()) && !statesInWorkList.get(predecessorEntry.getColumn())) { |
|||
worklist.push(predecessorEntry.getColumn()); |
|||
statesInWorkList.set(predecessorEntry.getColumn()); |
|||
} |
|||
} |
|||
markedStates.set(currentState, true); |
|||
} else { |
|||
markedStates.set(currentState, false); |
|||
} |
|||
|
|||
worklist.pop(); |
|||
statesInWorkList.set(currentState, false); |
|||
} |
|||
|
|||
return analysisInformation; |
|||
} |
|||
|
|||
/*! |
|||
* Computes a set of labels that is executed along all paths from an initial state to a target state. |
|||
* |
|||
* @param labelSet the considered label sets (a label set is assigned to each choice) |
|||
* |
|||
* @return The set of labels that is executed on all paths from an initial state to a target state. |
|||
*/ |
|||
template <typename T> |
|||
storm::storage::FlatSet<uint_fast64_t> getGuaranteedLabelSet(storm::models::sparse::Model<T> const& model, std::vector<storm::storage::FlatSet<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, storm::storage::FlatSet<uint_fast64_t> const& relevantLabels) { |
|||
std::vector<storm::storage::FlatSet<uint_fast64_t>> guaranteedLabels = getGuaranteedLabelSets(model, labelSets, psiStates, relevantLabels); |
|||
|
|||
storm::storage::FlatSet<uint_fast64_t> knownLabels(relevantLabels); |
|||
storm::storage::FlatSet<uint_fast64_t> tempIntersection; |
|||
for (auto initialState : model.getInitialStates()) { |
|||
std::set_intersection(knownLabels.begin(), knownLabels.end(), guaranteedLabels[initialState].begin(), guaranteedLabels[initialState].end(), std::inserter(tempIntersection, tempIntersection.end())); |
|||
std::swap(knownLabels, tempIntersection); |
|||
} |
|||
|
|||
return knownLabels; |
|||
} |
|||
|
|||
} // namespace counterexample |
|||
} // namespace storm |
@ -1,128 +0,0 @@ |
|||
#ifndef STORM_UTILITY_COUNTEREXAMPLE_H_ |
|||
#define STORM_UTILITY_COUNTEREXAMPLE_H_ |
|||
|
|||
#include <queue> |
|||
#include <utility> |
|||
|
|||
#include "storm/storage/sparse/PrismChoiceOrigins.h" |
|||
|
|||
namespace storm { |
|||
namespace utility { |
|||
namespace counterexamples { |
|||
|
|||
/*! |
|||
* Computes a set of labels that is executed along all paths from any state to a target state. |
|||
* |
|||
* @param labelSet the considered label sets (a label set is assigned to each choice) |
|||
* |
|||
* @return The set of labels that is visited on all paths from any state to a target state. |
|||
*/ |
|||
template <typename T> |
|||
std::vector<storm::storage::FlatSet<uint_fast64_t>> getGuaranteedLabelSets(storm::models::sparse::Model<T> const& model, std::vector<storm::storage::FlatSet<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, storm::storage::FlatSet<uint_fast64_t> const& relevantLabels) { |
|||
STORM_LOG_THROW(model.getNumberOfChoices() == labelSets.size(), storm::exceptions::InvalidArgumentException, "The given number of labels does not match the number of choices."); |
|||
|
|||
// Get some data from the model for convenient access. |
|||
storm::storage::SparseMatrix<T> const& transitionMatrix = model.getTransitionMatrix(); |
|||
std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices(); |
|||
storm::storage::SparseMatrix<T> backwardTransitions = model.getBackwardTransitions(); |
|||
|
|||
// Now we compute the set of labels that is present on all paths from the initial to the target states. |
|||
std::vector<storm::storage::FlatSet<uint_fast64_t>> analysisInformation(model.getNumberOfStates(), relevantLabels); |
|||
|
|||
std::queue<uint_fast64_t> worklist; |
|||
storm::storage::BitVector statesInWorkList(model.getNumberOfStates()); |
|||
storm::storage::BitVector markedStates(model.getNumberOfStates()); |
|||
|
|||
// Initially, put all predecessors of target states in the worklist and empty the analysis information them. |
|||
for (auto state : psiStates) { |
|||
analysisInformation[state] = storm::storage::FlatSet<uint_fast64_t>(); |
|||
for (auto const& predecessorEntry : backwardTransitions.getRow(state)) { |
|||
if (predecessorEntry.getColumn() != state && !statesInWorkList.get(predecessorEntry.getColumn()) && !psiStates.get(predecessorEntry.getColumn())) { |
|||
worklist.push(predecessorEntry.getColumn()); |
|||
statesInWorkList.set(predecessorEntry.getColumn()); |
|||
markedStates.set(state); |
|||
} |
|||
} |
|||
} |
|||
|
|||
uint_fast64_t iters = 0; |
|||
while (!worklist.empty()) { |
|||
++iters; |
|||
uint_fast64_t const& currentState = worklist.front(); |
|||
|
|||
size_t analysisInformationSizeBefore = analysisInformation[currentState].size(); |
|||
|
|||
// Iterate over the successor states for all choices and compute new analysis information. |
|||
for (uint_fast64_t currentChoice = nondeterministicChoiceIndices[currentState]; currentChoice < nondeterministicChoiceIndices[currentState + 1]; ++currentChoice) { |
|||
bool modifiedChoice = false; |
|||
|
|||
for (auto const& entry : transitionMatrix.getRow(currentChoice)) { |
|||
if (markedStates.get(entry.getColumn())) { |
|||
modifiedChoice = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
// If we can reach the target state with this choice, we need to intersect the current |
|||
// analysis information with the union of the new analysis information of the target state |
|||
// and the choice labels. |
|||
if (modifiedChoice) { |
|||
for (auto const& entry : transitionMatrix.getRow(currentChoice)) { |
|||
if (markedStates.get(entry.getColumn())) { |
|||
storm::storage::FlatSet<uint_fast64_t> tmpIntersection; |
|||
std::set_intersection(analysisInformation[currentState].begin(), analysisInformation[currentState].end(), analysisInformation[entry.getColumn()].begin(), analysisInformation[entry.getColumn()].end(), std::inserter(tmpIntersection, tmpIntersection.begin())); |
|||
std::set_intersection(analysisInformation[currentState].begin(), analysisInformation[currentState].end(), labelSets[currentChoice].begin(), labelSets[currentChoice].end(), std::inserter(tmpIntersection, tmpIntersection.begin())); |
|||
analysisInformation[currentState] = std::move(tmpIntersection); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// If the analysis information changed, we need to update it and put all the predecessors of this |
|||
// state in the worklist. |
|||
if (analysisInformation[currentState].size() != analysisInformationSizeBefore) { |
|||
for (auto const& predecessorEntry : backwardTransitions.getRow(currentState)) { |
|||
// Only put the predecessor in the worklist if it's not already a target state. |
|||
if (!psiStates.get(predecessorEntry.getColumn()) && !statesInWorkList.get(predecessorEntry.getColumn())) { |
|||
worklist.push(predecessorEntry.getColumn()); |
|||
statesInWorkList.set(predecessorEntry.getColumn()); |
|||
} |
|||
} |
|||
markedStates.set(currentState, true); |
|||
} else { |
|||
markedStates.set(currentState, false); |
|||
} |
|||
|
|||
worklist.pop(); |
|||
statesInWorkList.set(currentState, false); |
|||
} |
|||
|
|||
return analysisInformation; |
|||
} |
|||
|
|||
/*! |
|||
* Computes a set of labels that is executed along all paths from an initial state to a target state. |
|||
* |
|||
* @param labelSet the considered label sets (a label set is assigned to each choice) |
|||
* |
|||
* @return The set of labels that is executed on all paths from an initial state to a target state. |
|||
*/ |
|||
template <typename T> |
|||
storm::storage::FlatSet<uint_fast64_t> getGuaranteedLabelSet(storm::models::sparse::Model<T> const& model, std::vector<storm::storage::FlatSet<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, storm::storage::FlatSet<uint_fast64_t> const& relevantLabels) { |
|||
std::vector<storm::storage::FlatSet<uint_fast64_t>> guaranteedLabels = getGuaranteedLabelSets(model, labelSets, psiStates, relevantLabels); |
|||
|
|||
storm::storage::FlatSet<uint_fast64_t> knownLabels(relevantLabels); |
|||
storm::storage::FlatSet<uint_fast64_t> tempIntersection; |
|||
for (auto initialState : model.getInitialStates()) { |
|||
std::set_intersection(knownLabels.begin(), knownLabels.end(), guaranteedLabels[initialState].begin(), guaranteedLabels[initialState].end(), std::inserter(tempIntersection, tempIntersection.end())); |
|||
std::swap(knownLabels, tempIntersection); |
|||
} |
|||
|
|||
return knownLabels; |
|||
} |
|||
|
|||
} // namespace counterexample |
|||
} // namespace utility |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_UTILITY_COUNTEREXAMPLE_H_ */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue