Browse Source

reverted renaming of LabelSetGenerators to CommandSetGenerators. Potentially, these generators work for arbitrary sets of labels, not just for sets of Prism commands.

tempestpy_adaptions
TimQu 7 years ago
parent
commit
ecf3c7e996
  1. 4
      src/storm/api/counterexamples.cpp
  2. 4
      src/storm/api/counterexamples.h
  3. 2
      src/storm/cli/cli.cpp
  4. 141
      src/storm/counterexamples/MILPMinimalLabelSetGenerator.h
  5. 610
      src/storm/counterexamples/SMTMinimalLabelSetGenerator.h
  6. 38
      src/storm/utility/counterexamples.h

4
src/storm/api/counterexamples.cpp

@ -4,11 +4,11 @@ namespace storm {
namespace api {
std::shared_ptr<storm::counterexamples::Counterexample> computePrismHighLevelCounterexampleMilp(storm::prism::Program const& program, std::shared_ptr<storm::models::sparse::Mdp<double>> mdp, std::shared_ptr<storm::logic::Formula const> const& formula) {
return storm::counterexamples::MILPMinimalCommandSetGenerator<double>::computeCounterexample(program, *mdp, formula);
return storm::counterexamples::MILPMinimalLabelSetGenerator<double>::computeCounterexample(program, *mdp, formula);
}
std::shared_ptr<storm::counterexamples::Counterexample> computePrismHighLevelCounterexampleMaxSmt(storm::prism::Program const& program, std::shared_ptr<storm::models::sparse::Mdp<double>> mdp, std::shared_ptr<storm::logic::Formula const> const& formula) {
return storm::counterexamples::SMTMinimalCommandSetGenerator<double>::computeCounterexample(program, *mdp, formula);
return storm::counterexamples::SMTMinimalLabelSetGenerator<double>::computeCounterexample(program, *mdp, formula);
}
}

4
src/storm/api/counterexamples.h

@ -1,7 +1,7 @@
#pragma once
#include "storm/counterexamples/MILPMinimalCommandSetGenerator.h"
#include "storm/counterexamples/SMTMinimalCommandSetGenerator.h"
#include "storm/counterexamples/MILPMinimalLabelSetGenerator.h"
#include "storm/counterexamples/SMTMinimalLabelSetGenerator.h"
namespace storm {
namespace api {

2
src/storm/cli/cli.cpp

@ -497,7 +497,7 @@ namespace storm {
void printCounterexample(std::shared_ptr<storm::counterexamples::Counterexample> const& counterexample, storm::utility::Stopwatch* watch = nullptr) {
if (counterexample) {
STORM_PRINT_AND_LOG(counterexample << std::endl);
STORM_PRINT_AND_LOG(*counterexample << std::endl);
if (watch) {
STORM_PRINT_AND_LOG("Time for computation: " << *watch << "." << std::endl);
}

141
src/storm/counterexamples/MILPMinimalCommandSetGenerator.h → src/storm/counterexamples/MILPMinimalLabelSetGenerator.h

@ -2,6 +2,7 @@
#define STORM_COUNTEREXAMPLES_MILPMINIMALLABELSETGENERATOR_MDP_H_
#include <chrono>
#include <boost/container/flat_set.hpp>
#include "storm/models/sparse/Mdp.h"
#include "storm/logic/Formulas.h"
@ -33,10 +34,10 @@ namespace storm {
/*!
* This class provides functionality to generate a minimal counterexample to a probabilistic reachability
* property in terms of used commands.
* property in terms of used labels.
*/
template <class T>
class MILPMinimalCommandSetGenerator {
class MILPMinimalLabelSetGenerator {
private:
/*!
* A helper class that provides the functionality to compute a hash value for pairs of state indices.
@ -60,21 +61,21 @@ namespace storm {
};
/*!
* A helper struct capturing information about relevant and problematic choices of states and which commands
* A helper struct capturing information about relevant and problematic choices of states and which labels
* are relevant.
*/
struct ChoiceInformation {
std::unordered_map<uint_fast64_t, std::list<uint_fast64_t>> relevantChoicesForRelevantStates;
std::unordered_map<uint_fast64_t, std::list<uint_fast64_t>> problematicChoicesForProblematicStates;
boost::container::flat_set<uint_fast64_t> allRelevantCommands;
boost::container::flat_set<uint_fast64_t> knownCommands;
boost::container::flat_set<uint_fast64_t> allRelevantLabels;
boost::container::flat_set<uint_fast64_t> knownLabels;
};
/*!
* A helper struct capturing information about the variables of the MILP formulation.
*/
struct VariableInformation {
std::unordered_map<uint_fast64_t, storm::expressions::Variable> commandToVariableMap;
std::unordered_map<uint_fast64_t, storm::expressions::Variable> labelToVariableMap;
std::unordered_map<uint_fast64_t, std::list<storm::expressions::Variable>> stateToChoiceVariablesMap;
std::unordered_map<uint_fast64_t, storm::expressions::Variable> initialStateToChoiceVariableMap;
std::unordered_map<uint_fast64_t, storm::expressions::Variable> stateToProbabilityVariableMap;
@ -117,17 +118,16 @@ namespace storm {
* @param stateInformation The relevant and problematic states of the model.
* @param psiStates A bit vector characterizing the psi states in the model.
* @return A structure that stores the relevant and problematic choices in the model as well as the set
* of relevant commands.
* of relevant labels.
*/
static struct ChoiceInformation determineRelevantAndProblematicChoices(storm::models::sparse::Mdp<T> const& mdp, StateInformation const& stateInformation, storm::storage::BitVector const& psiStates) {
static struct ChoiceInformation determineRelevantAndProblematicChoices(storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, StateInformation const& stateInformation, storm::storage::BitVector const& psiStates) {
// Create result and shortcuts to needed data for convenience.
ChoiceInformation result;
storm::storage::SparseMatrix<T> const& transitionMatrix = mdp.getTransitionMatrix();
std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = mdp.getNondeterministicChoiceIndices();
storm::storage::sparse::PrismChoiceOrigins const& choiceOrigins = mdp.getChoiceOrigins()->asPrismChoiceOrigins();
// Now traverse all choices of all relevant states and check whether there is a relevant target state.
// If so, the associated commands become relevant. Also, if a choice of relevant state has at least one
// If so, the associated labels become relevant. Also, if a choice of relevant state has at least one
// relevant successor, the choice is considered to be relevant.
for (auto state : stateInformation.relevantStates) {
result.relevantChoicesForRelevantStates.emplace(state, std::list<uint_fast64_t>());
@ -138,10 +138,10 @@ namespace storm {
bool currentChoiceRelevant = false;
bool allSuccessorsProblematic = true;
for (auto const& successorEntry : transitionMatrix.getRow(row)) {
// If there is a relevant successor, we need to add the commands of the current choice.
// If there is a relevant successor, we need to add the labels of the current choice.
if (stateInformation.relevantStates.get(successorEntry.getColumn()) || psiStates.get(successorEntry.getColumn())) {
for (auto const& command : choiceOrigins.getCommandSet(row)) {
result.allRelevantCommands.insert(command);
for (auto const& label : labelSets[row]) {
result.allRelevantLabels.insert(label);
}
if (!currentChoiceRelevant) {
currentChoiceRelevant = true;
@ -161,30 +161,30 @@ namespace storm {
}
}
// Finally, determine the set of commands that are known to be taken.
result.knownCommands = storm::utility::counterexamples::getGuaranteedCommandSet(mdp, psiStates, result.allRelevantCommands);
STORM_LOG_DEBUG("Found " << result.allRelevantCommands.size() << " relevant commands and " << result.knownCommands.size() << " known commands.");
// Finally, determine the set of labels that are known to be taken.
result.knownLabels = storm::utility::counterexamples::getGuaranteedLabelSet(mdp, labelSets, psiStates, result.allRelevantLabels);
STORM_LOG_DEBUG("Found " << result.allRelevantLabels.size() << " relevant labels and " << result.knownLabels.size() << " known labels.");
return result;
}
/*!
* Creates the variables for the commands of the model.
* Creates the variables for the labels of the model.
*
* @param solver The MILP solver.
* @param relevantCommands The set of relevant commands of the model.
* @return A mapping from commands to variable indices.
* @param relevantLabels The set of relevant labels of the model.
* @return A mapping from labels to variable indices.
*/
static std::pair<std::unordered_map<uint_fast64_t, storm::expressions::Variable>, uint_fast64_t> createCommandVariables(storm::solver::LpSolver& solver, boost::container::flat_set<uint_fast64_t> const& relevantCommands) {
static std::pair<std::unordered_map<uint_fast64_t, storm::expressions::Variable>, uint_fast64_t> createLabelVariables(storm::solver::LpSolver& solver, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
std::stringstream variableNameBuffer;
std::unordered_map<uint_fast64_t, storm::expressions::Variable> resultingMap;
for (auto const& command : relevantCommands) {
for (auto const& label : relevantLabels) {
variableNameBuffer.str("");
variableNameBuffer.clear();
variableNameBuffer << "command" << command;
resultingMap[command] = solver.addBinaryVariable(variableNameBuffer.str(), 1);
variableNameBuffer << "label" << label;
resultingMap[label] = solver.addBinaryVariable(variableNameBuffer.str(), 1);
}
return std::make_pair(resultingMap, relevantCommands.size());
return std::make_pair(resultingMap, relevantLabels.size());
}
/*!
@ -363,11 +363,11 @@ namespace storm {
// Create a struct that stores all information about variables.
VariableInformation result;
// Create variables for involved commands.
std::pair<std::unordered_map<uint_fast64_t, storm::expressions::Variable>, uint_fast64_t> commandVariableResult = createCommandVariables(solver, choiceInformation.allRelevantCommands);
result.commandToVariableMap = std::move(commandVariableResult.first);
result.numberOfVariables += commandVariableResult.second;
STORM_LOG_DEBUG("Created variables for commands.");
// Create variables for involved labels.
std::pair<std::unordered_map<uint_fast64_t, storm::expressions::Variable>, uint_fast64_t> labelVariableResult = createLabelVariables(solver, choiceInformation.allRelevantLabels);
result.labelToVariableMap = std::move(labelVariableResult.first);
result.numberOfVariables += labelVariableResult.second;
STORM_LOG_DEBUG("Created variables for labels.");
// Create scheduler variables for relevant states and their actions.
std::pair<std::unordered_map<uint_fast64_t, std::list<storm::expressions::Variable>>, uint_fast64_t> schedulerVariableResult = createSchedulerVariables(solver, stateInformation, choiceInformation);
@ -474,8 +474,8 @@ namespace storm {
}
/*!
* Asserts constraints that make sure the commands are included in the solution set if the policy selects a
* choice that originates from the command in question.
* Asserts constraints that make sure the labels are included in the solution set if the policy selects a
* choice that originates from the label in question.
*
* @param solver The MILP solver.
* @param mdp The MDP.
@ -484,17 +484,16 @@ namespace storm {
* @param variableInformation A struct with information about the variables of the model.
* @return The total number of constraints that were created.
*/
static uint_fast64_t assertChoicesImplyCommands(storm::solver::LpSolver& solver, storm::models::sparse::Mdp<T> const& mdp, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation, VariableInformation const& variableInformation) {
storm::storage::sparse::PrismChoiceOrigins const& choiceOrigins = mdp.getChoiceOrigins()->asPrismChoiceOrigins();
static uint_fast64_t assertChoicesImplyLabels(storm::solver::LpSolver& solver, storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation, VariableInformation const& variableInformation) {
uint_fast64_t numberOfConstraintsCreated = 0;
for (auto state : stateInformation.relevantStates) {
std::list<storm::expressions::Variable>::const_iterator choiceVariableIterator = variableInformation.stateToChoiceVariablesMap.at(state).begin();
for (auto choice : choiceInformation.relevantChoicesForRelevantStates.at(state)) {
for (auto command : choiceOrigins.getCommandSet(choice)) {
storm::expressions::Expression constraint = variableInformation.commandToVariableMap.at(command) - *choiceVariableIterator >= solver.getConstant(0);
solver.addConstraint("ChoicesImplyCommands" + std::to_string(numberOfConstraintsCreated), constraint);
for (auto label : labelSets[choice]) {
storm::expressions::Expression constraint = variableInformation.labelToVariableMap.at(label) - *choiceVariableIterator >= solver.getConstant(0);
solver.addConstraint("ChoicesImplyLabels" + std::to_string(numberOfConstraintsCreated), constraint);
++numberOfConstraintsCreated;
}
++choiceVariableIterator;
@ -623,19 +622,19 @@ namespace storm {
}
/*
* Asserts that commands that are on all paths from initial to target states are definitely taken.
* Asserts that labels that are on all paths from initial to target states are definitely taken.
*
* @param solver The MILP solver.
* @param choiceInformation The information about the choices in the model.
* @param variableInformation A struct with information about the variables of the model.
* @return The total number of constraints that were created.
*/
static uint_fast64_t assertKnownCommands(storm::solver::LpSolver& solver, ChoiceInformation const& choiceInformation, VariableInformation const& variableInformation) {
static uint_fast64_t assertKnownLabels(storm::solver::LpSolver& solver, ChoiceInformation const& choiceInformation, VariableInformation const& variableInformation) {
uint_fast64_t numberOfConstraintsCreated = 0;
for (auto command : choiceInformation.knownCommands) {
storm::expressions::Expression constraint = variableInformation.commandToVariableMap.at(command) == solver.getConstant(1);
solver.addConstraint("KnownCommands" + std::to_string(numberOfConstraintsCreated), constraint);
for (auto label : choiceInformation.knownLabels) {
storm::expressions::Expression constraint = variableInformation.labelToVariableMap.at(label) == solver.getConstant(1);
solver.addConstraint("KnownLabels" + std::to_string(numberOfConstraintsCreated), constraint);
++numberOfConstraintsCreated;
}
@ -813,7 +812,7 @@ namespace storm {
* @param includeSchedulerCuts If set to true, additional constraints are asserted that reduce the set of
* possible choices.
*/
static void buildConstraintSystem(storm::solver::LpSolver& solver, storm::models::sparse::Mdp<T> const& mdp, storm::storage::BitVector const& psiStates, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation, VariableInformation const& variableInformation, double probabilityThreshold, bool strictBound, bool includeSchedulerCuts = false) {
static void buildConstraintSystem(storm::solver::LpSolver& solver, storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation, VariableInformation const& variableInformation, double probabilityThreshold, bool strictBound, bool includeSchedulerCuts = false) {
// Assert that the reachability probability in the subsystem exceeds the given threshold.
uint_fast64_t numberOfConstraints = assertProbabilityGreaterThanThreshold(solver, variableInformation, probabilityThreshold, strictBound);
STORM_LOG_DEBUG("Asserted that reachability probability exceeds threshold.");
@ -822,9 +821,9 @@ namespace storm {
numberOfConstraints += assertValidPolicy(solver, stateInformation, variableInformation);
STORM_LOG_DEBUG("Asserted that policy is valid.");
// Add constraints that assert the commands that belong to some taken choices are taken as well.
numberOfConstraints += assertChoicesImplyCommands(solver, mdp, stateInformation, choiceInformation, variableInformation);
STORM_LOG_DEBUG("Asserted that commands implied by choices are taken.");
// Add constraints that assert the labels that belong to some taken choices are taken as well.
numberOfConstraints += assertChoicesImplyLabels(solver, mdp, labelSets, stateInformation, choiceInformation, variableInformation);
STORM_LOG_DEBUG("Asserted that labels implied by choices are taken.");
// Add constraints that encode that the reachability probability from states which do not pick any action
// is zero.
@ -839,9 +838,9 @@ namespace storm {
numberOfConstraints += assertUnproblematicStateReachable(solver, mdp, stateInformation, choiceInformation, variableInformation);
STORM_LOG_DEBUG("Asserted that unproblematic state reachable from problematic states.");
// Add constraints that express that certain commands are already known to be taken.
numberOfConstraints += assertKnownCommands(solver, choiceInformation, variableInformation);
STORM_LOG_DEBUG("Asserted known commands are taken.");
// Add constraints that express that certain labels are already known to be taken.
numberOfConstraints += assertKnownLabels(solver, choiceInformation, variableInformation);
STORM_LOG_DEBUG("Asserted known labels are taken.");
// If required, assert additional constraints that reduce the number of possible policies.
if (includeSchedulerCuts) {
@ -861,14 +860,14 @@ namespace storm {
* @param solver The MILP solver.
* @param variableInformation A struct with information about the variables of the model.
*/
static boost::container::flat_set<uint_fast64_t> getUsedCommandsInSolution(storm::solver::LpSolver const& solver, VariableInformation const& variableInformation) {
static boost::container::flat_set<uint_fast64_t> getUsedLabelsInSolution(storm::solver::LpSolver const& solver, VariableInformation const& variableInformation) {
boost::container::flat_set<uint_fast64_t> result;
for (auto const& commandVariablePair : variableInformation.commandToVariableMap) {
bool commandTaken = solver.getBinaryValue(commandVariablePair.second);
for (auto const& labelVariablePair : variableInformation.labelToVariableMap) {
bool labelTaken = solver.getBinaryValue(labelVariablePair.second);
if (commandTaken) {
result.insert(commandVariablePair.first);
if (labelTaken) {
result.insert(labelVariablePair.first);
}
}
return result;
@ -923,10 +922,9 @@ namespace storm {
}
public:
static boost::container::flat_set<uint_fast64_t> getMinimalCommandSet(storm::models::sparse::Mdp<T> const& mdp, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, double probabilityThreshold, bool strictBound, bool checkThresholdFeasible = false, bool includeSchedulerCuts = false) {
// (0) Check whether there are choice origins available
STORM_LOG_THROW(mdp.hasChoiceOrigins(), storm::exceptions::InvalidArgumentException, "Restriction to command set is impossible for model without choice origns.");
STORM_LOG_THROW(mdp.getChoiceOrigins()->isPrismChoiceOrigins(), storm::exceptions::InvalidArgumentException, "Restriction to command set is impossible for model without prism choice origins.");
static boost::container::flat_set<uint_fast64_t> getMinimalLabelSet(storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, double probabilityThreshold, bool strictBound, bool checkThresholdFeasible = false, bool includeSchedulerCuts = false) {
// (0) Check whether the label sets are valid
STORM_LOG_THROW(mdp.getNumberOfChoices() == labelSets.size(), storm::exceptions::InvalidArgumentException, "The given number of labels does not match the number of choices.");
// (1) Check whether its possible to exceed the threshold if checkThresholdFeasible is set.
double maximalReachabilityProbability = 0;
@ -943,27 +941,27 @@ namespace storm {
// (2) Identify relevant and problematic states.
StateInformation stateInformation = determineRelevantAndProblematicStates(mdp, phiStates, psiStates);
// (3) Determine sets of relevant commands and problematic choices.
ChoiceInformation choiceInformation = determineRelevantAndProblematicChoices(mdp, stateInformation, psiStates);
// (3) Determine sets of relevant labels and problematic choices.
ChoiceInformation choiceInformation = determineRelevantAndProblematicChoices(mdp, labelSets, stateInformation, psiStates);
// (4) Encode resulting system as MILP problem.
std::shared_ptr<storm::solver::LpSolver> solver = storm::utility::solver::getLpSolver("MinimalCommandSetCounterexample");
std::shared_ptr<storm::solver::LpSolver> solver = storm::utility::solver::getLpSolver("MinimalLabelSetCounterexample");
// (4.1) Create variables.
VariableInformation variableInformation = createVariables(*solver, mdp, stateInformation, choiceInformation);
// (4.2) Construct constraint system.
buildConstraintSystem(*solver, mdp, psiStates, stateInformation, choiceInformation, variableInformation, probabilityThreshold, strictBound, includeSchedulerCuts);
buildConstraintSystem(*solver, mdp, labelSets, psiStates, stateInformation, choiceInformation, variableInformation, probabilityThreshold, strictBound, includeSchedulerCuts);
// (4.3) Optimize the model.
solver->optimize();
// (4.4) Read off result from variables.
boost::container::flat_set<uint_fast64_t> usedCommandSet = getUsedCommandsInSolution(*solver, variableInformation);
usedCommandSet.insert(choiceInformation.knownCommands.begin(), choiceInformation.knownCommands.end());
boost::container::flat_set<uint_fast64_t> usedLabelSet = getUsedLabelsInSolution(*solver, variableInformation);
usedLabelSet.insert(choiceInformation.knownLabels.begin(), choiceInformation.knownLabels.end());
// (5) Return result.
return usedCommandSet;
return usedLabelSet;
}
/*!
@ -976,6 +974,10 @@ namespace storm {
static std::shared_ptr<PrismHighLevelCounterexample> computeCounterexample(storm::prism::Program const& program, storm::models::sparse::Mdp<T> const& mdp, std::shared_ptr<storm::logic::Formula const> const& formula) {
std::cout << std::endl << "Generating minimal label counterexample for formula " << *formula << std::endl;
// Check whether there are choice origins available
STORM_LOG_THROW(mdp.hasChoiceOrigins(), storm::exceptions::InvalidArgumentException, "Restriction to minimal command set is impossible for model without choice origns.");
STORM_LOG_THROW(mdp.getChoiceOrigins()->isPrismChoiceOrigins(), storm::exceptions::InvalidArgumentException, "Restriction to command set is impossible for model without prism choice origins.");
STORM_LOG_THROW(formula->isProbabilityOperatorFormula(), storm::exceptions::InvalidPropertyException, "Counterexample generation does not support this kind of formula. Expecting a probability operator as the outermost formula element.");
storm::logic::ProbabilityOperatorFormula const& probabilityOperator = formula->asProbabilityOperatorFormula();
STORM_LOG_THROW(probabilityOperator.hasBound(), storm::exceptions::InvalidPropertyException, "Counterexample generation only supports bounded formulas.");
@ -1012,9 +1014,18 @@ namespace storm {
psiStates = subQualitativeResult.getTruthValuesVector();
}
// Obtain the label sets for each choice.
// The label set of a choice corresponds to the set of prism commands that induce the choice.
storm::storage::sparse::PrismChoiceOrigins const& choiceOrigins = mdp.getChoiceOrigins()->asPrismChoiceOrigins();
std::vector<boost::container::flat_set<uint_fast64_t>> labelSets;
labelSets.reserve(mdp.getNumberOfChoices());
for (uint_fast64_t choice = 0; choice < mdp.getNumberOfChoices(); ++choice) {
labelSets.push_back(choiceOrigins.getCommandSet(choice));
}
// Delegate the actual computation work to the function of equal name.
auto startTime = std::chrono::high_resolution_clock::now();
boost::container::flat_set<uint_fast64_t> usedCommandSet = getMinimalCommandSet(mdp, phiStates, psiStates, threshold, strictBound, true, storm::settings::getModule<storm::settings::modules::CounterexampleGeneratorSettings>().isUseSchedulerCutsSet());
boost::container::flat_set<uint_fast64_t> usedCommandSet = getMinimalLabelSet(mdp, labelSets, phiStates, psiStates, threshold, strictBound, true, storm::settings::getModule<storm::settings::modules::CounterexampleGeneratorSettings>().isUseSchedulerCutsSet());
auto endTime = std::chrono::high_resolution_clock::now();
std::cout << std::endl << "Computed minimal command set of size " << usedCommandSet.size() << " in " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() << "ms." << std::endl;

610
src/storm/counterexamples/SMTMinimalLabelSetGenerator.h
File diff suppressed because it is too large
View File

38
src/storm/utility/counterexamples.h

@ -11,23 +11,23 @@ namespace storm {
namespace counterexamples {
/*!
* Computes a set of Prism commands that is executed along all paths from any state to a target state.
* Computes a set of labels that is executed along all paths from any state to a target state.
*
* @return The set of Prism commands that is visited on 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<boost::container::flat_set<uint_fast64_t>> getGuaranteedCommandSets(storm::models::sparse::Mdp<T> const& mdp, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantCommands) {
STORM_LOG_THROW(mdp.hasChoiceOrigins(), storm::exceptions::InvalidArgumentException, "Restriction to command set is impossible for model without choice origns.");
STORM_LOG_THROW(mdp.getChoiceOrigins()->isPrismChoiceOrigins(), storm::exceptions::InvalidArgumentException, "Restriction to command set is impossible for model without prism choice origins.");
std::vector<boost::container::flat_set<uint_fast64_t>> getGuaranteedLabelSets(storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
STORM_LOG_THROW(mdp.getNumberOfChoices() == labelSets.size(), storm::exceptions::InvalidArgumentException, "The given number of labels does not match the number of choices.");
// Get some data from the MDP for convenient access.
storm::storage::SparseMatrix<T> const& transitionMatrix = mdp.getTransitionMatrix();
std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = mdp.getNondeterministicChoiceIndices();
storm::storage::SparseMatrix<T> backwardTransitions = mdp.getBackwardTransitions();
storm::storage::sparse::PrismChoiceOrigins const& choiceOrigins = mdp.getChoiceOrigins()->asPrismChoiceOrigins();
// Now we compute the set of commands that is present on all paths from the initial to the target states.
std::vector<boost::container::flat_set<uint_fast64_t>> analysisInformation(mdp.getNumberOfStates(), relevantCommands);
// Now we compute the set of labels that is present on all paths from the initial to the target states.
std::vector<boost::container::flat_set<uint_fast64_t>> analysisInformation(mdp.getNumberOfStates(), relevantLabels);
std::queue<uint_fast64_t> worklist;
storm::storage::BitVector statesInWorkList(mdp.getNumberOfStates());
@ -65,13 +65,13 @@ namespace storm {
// 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 commands.
// and the choice labels.
if (modifiedChoice) {
for (auto const& entry : transitionMatrix.getRow(currentChoice)) {
if (markedStates.get(entry.getColumn())) {
boost::container::flat_set<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(), choiceOrigins.getCommandSet(currentChoice).begin(), choiceOrigins.getCommandSet(currentChoice).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);
}
}
@ -101,22 +101,24 @@ namespace storm {
}
/*!
* Computes a set of prism commands that is executed along all paths from an initial state to a target state.
* 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 prism commands that is executed on all paths from an initial state to a target state.
* @return The set of labels that is executed on all paths from an initial state to a target state.
*/
template <typename T>
boost::container::flat_set<uint_fast64_t> getGuaranteedCommandSet(storm::models::sparse::Mdp<T> const& mdp, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantCommands) {
std::vector<boost::container::flat_set<uint_fast64_t>> guaranteedCommands = getGuaranteedCommandSets(mdp, psiStates, relevantCommands);
boost::container::flat_set<uint_fast64_t> getGuaranteedLabelSet(storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
std::vector<boost::container::flat_set<uint_fast64_t>> guaranteedLabels = getGuaranteedLabelSets(mdp, labelSets, psiStates, relevantLabels);
boost::container::flat_set<uint_fast64_t> knownCommands(relevantCommands);
boost::container::flat_set<uint_fast64_t> knownLabels(relevantLabels);
boost::container::flat_set<uint_fast64_t> tempIntersection;
for (auto initialState : mdp.getInitialStates()) {
std::set_intersection(knownCommands.begin(), knownCommands.end(), guaranteedCommands[initialState].begin(), guaranteedCommands[initialState].end(), std::inserter(tempIntersection, tempIntersection.end()));
std::swap(knownCommands, tempIntersection);
std::set_intersection(knownLabels.begin(), knownLabels.end(), guaranteedLabels[initialState].begin(), guaranteedLabels[initialState].end(), std::inserter(tempIntersection, tempIntersection.end()));
std::swap(knownLabels, tempIntersection);
}
return knownCommands;
return knownLabels;
}
} // namespace counterexample

Loading…
Cancel
Save