Browse Source

Merge remote-tracking branch 'origin/master' into janiTests

tempestpy_adaptions
dehnert 6 years ago
parent
commit
8213790089
  1. 9
      CHANGELOG.md
  2. 4
      src/storm-conv/converter/options/JaniConversionOptions.cpp
  3. 2
      src/storm-conv/converter/options/PrismToJaniConverterOptions.cpp
  4. 1072
      src/storm-dft/modelchecker/dft/DFTASFChecker.cpp
  5. 32
      src/storm-dft/modelchecker/dft/DFTASFChecker.h
  6. 28
      src/storm-parsers/parser/JaniParser.cpp
  7. 6
      src/storm-parsers/parser/PrismParser.cpp
  8. 36
      src/storm/logic/RewardAccumulationEliminationVisitor.cpp
  9. 8
      src/storm/storage/jani/Automaton.cpp
  10. 8
      src/storm/storage/jani/JSONExporter.cpp
  11. 20
      src/storm/storage/jani/Model.cpp
  12. 13
      src/storm/storage/jani/Model.h
  13. 2
      src/storm/storage/prism/Program.cpp
  14. 3
      src/storm/transformer/SubsystemBuilder.cpp
  15. 103
      src/storm/utility/graph.cpp
  16. 2
      src/storm/utility/graph.h
  17. 3
      src/storm/utility/shortestPaths.h

9
CHANGELOG.md

@ -8,10 +8,15 @@ Version 1.2.x
-------------
### Version 1.2.4 (2018/08)
- New binary `storm-conv` that handles conversions between model files (currently: prism to jani)
- Heavily extended JANI support, in particular:
* arrays, functions, state-exit-rewards (all engines)
* indexed assignments, complex reward expressions (sparse engine)
* several jani-related bug fixes
- New binary `storm-conv` that handles conversions between model files
- New binary `storm-pomdp` that handles the translation of POMDPs to pMCs.
- Closing a Markov automaton now removes unreachable states
- Added support for expected time properties for discrete time models
- Bug fix in the parser for DRN (MDPs and MAs might have been affected).
- Several bug fixes related to jani
- `storm-gspn`: Improved .pnpro parser
- `storm-gspn`: Added support for single/infinite/k-server semantics for GSPNs given in the .pnpro format
- `storm-gspn`: Added option to set a global capacity for all places

4
src/storm-conv/converter/options/JaniConversionOptions.cpp

@ -5,7 +5,7 @@ namespace storm {
JaniConversionOptions::JaniConversionOptions() : edgeAssignments(false), flatten(false), substituteConstants(true), allowedModelFeatures(storm::jani::getAllKnownModelFeatures()) {
// Intentionally left empty
};
}
JaniConversionOptions::JaniConversionOptions(storm::settings::modules::JaniExportSettings const& settings) : locationVariables(settings.getLocationVariables()), edgeAssignments(settings.isAllowEdgeAssignmentsSet()), flatten(settings.isExportFlattenedSet()), substituteConstants(true), allowedModelFeatures(storm::jani::getAllKnownModelFeatures()) {
if (settings.isEliminateFunctionsSet()) {
@ -14,7 +14,7 @@ namespace storm {
if (settings.isEliminateArraysSet()) {
allowedModelFeatures.remove(storm::jani::ModelFeature::Arrays);
}
};
}
}
}

2
src/storm-conv/converter/options/PrismToJaniConverterOptions.cpp

@ -6,7 +6,7 @@ namespace storm {
PrismToJaniConverterOptions::PrismToJaniConverterOptions() : allVariablesGlobal(false), suffix("") {
// Intentionally left empty
};
}
}
}

1072
src/storm-dft/modelchecker/dft/DFTASFChecker.cpp
File diff suppressed because it is too large
View File

32
src/storm-dft/modelchecker/dft/DFTASFChecker.h

@ -12,11 +12,13 @@ namespace storm {
class DFTConstraint {
public:
virtual ~DFTConstraint() {
}
virtual std::string toSmtlib2(std::vector<std::string> const& varNames) const = 0;
virtual std::string description() const { return descript; }
virtual std::string toSmtlib2(std::vector<std::string> const& varNames) const = 0;
virtual std::string description() const {
return descript;
}
void setDescription(std::string const& descr) {
descript = descr;
@ -27,10 +29,8 @@ namespace storm {
};
class SpareAndChildPair {
public:
SpareAndChildPair(uint64_t spareIndex, uint64_t childIndex) : spareIndex(spareIndex), childIndex(childIndex) {
}
friend bool operator<(SpareAndChildPair const& p1, SpareAndChildPair const& p2) {
@ -45,7 +45,6 @@ namespace storm {
class DFTASFChecker {
using ValueType = double;
public:
DFTASFChecker(storm::storage::DFT<ValueType> const&);
void convert();
@ -53,12 +52,33 @@ namespace storm {
private:
uint64_t getClaimVariableIndex(uint64_t spareIndex, uint64_t childIndex) const;
/**
* Generate constraint for 'spare (s) tries to claim the child (i) at the given timepoint (t)'.
* This corresponds to the function \phi^s_i(t) in constraint 7.
*
* @param spare Spare.
* @param childIndex Index of child to consider in spare children.
* @param timepoint Timepoint to try to claim.
*
* @return Constraint encoding the claiming.
*/
std::shared_ptr<DFTConstraint> generateTryToClaimConstraint(std::shared_ptr<storm::storage::DFTSpare<ValueType> const> spare, uint64_t childIndex, uint64_t timepoint) const;
/**
* Add constraints encoding Markovian states.
* This corresponds to constraints (9), (10) and (11)
*/
void addMarkovianConstraints();
storm::storage::DFT<ValueType> const& dft;
std::vector<std::string> varNames;
std::unordered_map<uint64_t, uint64_t> timePointVariables;
std::vector<std::shared_ptr<DFTConstraint>> constraints;
std::map<SpareAndChildPair, uint64_t> claimVariables;
std::unordered_map<uint64_t, uint64_t> markovianVariables;
std::vector<uint64_t> tmpTimePointVariables;
uint64_t notFailed;
};
}
}

28
src/storm-parsers/parser/JaniParser.cpp

@ -205,7 +205,11 @@ namespace storm {
STORM_LOG_THROW(parsedStructure.at("properties").is_array(), storm::exceptions::InvalidJaniException, "Properties should be an array");
for(auto const& propertyEntry : parsedStructure.at("properties")) {
try {
nonTrivialRewardModelExpressions.clear();
auto prop = this->parseProperty(propertyEntry, scope.refine("property[" + std::to_string(properties.size()) + "]"));
for (auto const& nonTrivRewExpr : nonTrivialRewardModelExpressions) {
model.addNonTrivialRewardExpression(nonTrivRewExpr.first, nonTrivRewExpr.second);
}
// Eliminate reward accumulations as much as possible
rewAccEliminator.eliminateRewardAccumulations(prop);
properties.push_back(prop);
@ -321,7 +325,10 @@ namespace storm {
STORM_LOG_THROW(propertyStructure.count("reward-instants") == 0, storm::exceptions::NotSupportedException, "Storm does not support to have a step-instant and a reward-instant in " + scope.description);
storm::expressions::Expression stepInstantExpr = parseExpression(propertyStructure.at("step-instant"), scope.refine("Step instant"));
if(rewardAccumulation.isEmpty()) {
if (!rewExpr.isVariable()) {
nonTrivialRewardModelExpressions.emplace(rewardName, rewExpr);
}
if (rewardAccumulation.isEmpty()) {
return std::make_shared<storm::logic::RewardOperatorFormula>(std::make_shared<storm::logic::InstantaneousRewardFormula>(stepInstantExpr, storm::logic::TimeBoundType::Steps), rewardName, opInfo);
} else {
return std::make_shared<storm::logic::RewardOperatorFormula>(std::make_shared<storm::logic::CumulativeRewardFormula>(storm::logic::TimeBound(false, stepInstantExpr), storm::logic::TimeBoundReference(storm::logic::TimeBoundType::Steps), rewardAccumulation), rewardName, opInfo);
@ -329,7 +336,10 @@ namespace storm {
} else if (propertyStructure.count("time-instant") > 0) {
STORM_LOG_THROW(propertyStructure.count("reward-instants") == 0, storm::exceptions::NotSupportedException, "Storm does not support to have a time-instant and a reward-instant in " + scope.description);
storm::expressions::Expression timeInstantExpr = parseExpression(propertyStructure.at("time-instant"), scope.refine("time instant"));
if(rewardAccumulation.isEmpty()) {
if (!rewExpr.isVariable()) {
nonTrivialRewardModelExpressions.emplace(rewardName, rewExpr);
}
if (rewardAccumulation.isEmpty()) {
return std::make_shared<storm::logic::RewardOperatorFormula>(std::make_shared<storm::logic::InstantaneousRewardFormula>(timeInstantExpr, storm::logic::TimeBoundType::Time), rewardName, opInfo);
} else {
return std::make_shared<storm::logic::RewardOperatorFormula>(std::make_shared<storm::logic::CumulativeRewardFormula>(storm::logic::TimeBound(false, timeInstantExpr), storm::logic::TimeBoundReference(storm::logic::TimeBoundType::Time), rewardAccumulation), rewardName, opInfo);
@ -349,6 +359,9 @@ namespace storm {
storm::expressions::Expression rewInstantExpr = parseExpression(rewInst.at("instant"), scope.refine("reward instant"));
bounds.emplace_back(false, rewInstantExpr);
}
if (!rewExpr.isVariable()) {
nonTrivialRewardModelExpressions.emplace(rewardName, rewExpr);
}
return std::make_shared<storm::logic::RewardOperatorFormula>(std::make_shared<storm::logic::CumulativeRewardFormula>(bounds, boundReferences, rewardAccumulation), rewardName, opInfo);
} else {
time = !rewExpr.containsVariables() && storm::utility::isOne(rewExpr.evaluateAsRational());
@ -363,12 +376,12 @@ namespace storm {
assert(subformula->isTotalRewardFormula() || subformula->isTimePathFormula());
return std::make_shared<storm::logic::TimeOperatorFormula>(subformula, opInfo);
} else {
if (!rewExpr.isVariable()) {
nonTrivialRewardModelExpressions.emplace(rewardName, rewExpr);
}
return std::make_shared<storm::logic::RewardOperatorFormula>(subformula, rewardName, opInfo);
}
}
if (!time && !rewExpr.isVariable()) {
nonTrivialRewardModelExpressions.emplace(rewardName, rewExpr);
}
} else if (opString == "Smin" || opString == "Smax") {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Smin and Smax are currently not supported");
} else if (opString == "U" || opString == "F") {
@ -829,9 +842,9 @@ namespace storm {
}
} else {
if (type.bounds) {
return std::make_shared<storm::jani::UnboundedIntegerVariable>(name, expressionManager->declareIntegerVariable(exprManagerName), initVal.get(), transientVar);
} else {
return storm::jani::makeBoundedIntegerVariable(name, expressionManager->declareIntegerVariable(exprManagerName), boost::none, false, type.bounds->first, type.bounds->second);
} else {
return std::make_shared<storm::jani::UnboundedIntegerVariable>(name, expressionManager->declareIntegerVariable(exprManagerName));
}
}
break;
@ -1403,6 +1416,7 @@ namespace storm {
STORM_LOG_THROW(edgeEntry.at("rate").count("exp") == 1, storm::exceptions::InvalidJaniException, "Rate in edge from '" << sourceLoc << "' in automaton '" << name << "' must have a defing expression.");
rateExpr = parseExpression(edgeEntry.at("rate").at("exp"), scope.refine("rate expression in edge from '" + sourceLoc));
STORM_LOG_THROW(rateExpr.hasNumericalType(), storm::exceptions::InvalidJaniException, "Rate '" << rateExpr << "' has not a numerical type");
STORM_LOG_THROW(rateExpr.containsVariables() || rateExpr.evaluateAsRational() > storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidJaniException, "Only positive rates are allowed but rate '" << rateExpr << " was found.");
}
// guard
STORM_LOG_THROW(edgeEntry.count("guard") <= 1, storm::exceptions::InvalidJaniException, "Guard can be given at most once in edge from '" << sourceLoc << "' in automaton '" << name << "'");

6
src/storm-parsers/parser/PrismParser.cpp

@ -561,7 +561,6 @@ namespace storm {
bool observable = this->observables.count(variableName) > 0;
if(observable) {
this->observables.erase(variableName);
std::cout << variableName << " is observable." << std::endl;
}
return storm::prism::BooleanVariable(manager->getVariable(variableName), initialValueExpression, observable, this->getFilename());
}
@ -582,7 +581,6 @@ namespace storm {
bool observable = this->observables.count(variableName) > 0;
if(observable) {
this->observables.erase(variableName);
std::cout << variableName << " is observable." << std::endl;
}
return storm::prism::IntegerVariable(manager->getVariable(variableName), lowerBoundExpression, upperBoundExpression, initialValueExpression, observable, this->getFilename());
@ -613,7 +611,6 @@ namespace storm {
this->identifiers_.add(renamingPair->second, renamedVariable.getExpression());
if(this->observables.count(renamingPair->second) > 0) {
this->observables.erase(renamingPair->second);
std::cout << renamingPair->second << " is observable." << std::endl;
}
}
for (auto const& variable : moduleToRename.getIntegerVariables()) {
@ -623,7 +620,6 @@ namespace storm {
this->identifiers_.add(renamingPair->second, renamedVariable.getExpression());
if(this->observables.count(renamingPair->second) > 0) {
this->observables.erase(renamingPair->second);
std::cout << renamingPair->second << " is observable." << std::endl;
}
}
@ -666,7 +662,6 @@ namespace storm {
bool observable = this->observables.count(renamingPair->second) > 0;
if(observable) {
this->observables.erase(renamingPair->second);
std::cout << renamingPair->second << " is observable." << std::endl;
}
booleanVariables.push_back(storm::prism::BooleanVariable(manager->getVariable(renamingPair->second), variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(), observable, this->getFilename(), get_line(qi::_1)));
}
@ -679,7 +674,6 @@ namespace storm {
bool observable = this->observables.count(renamingPair->second) > 0;
if(observable) {
this->observables.erase(renamingPair->second);
std::cout << renamingPair->second << " is observable." << std::endl;
}
integerVariables.push_back(storm::prism::IntegerVariable(manager->getVariable(renamingPair->second), variable.getLowerBoundExpression().substitute(expressionRenaming), variable.getUpperBoundExpression().substitute(expressionRenaming), variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(), observable, this->getFilename(), get_line(qi::_1)));
}

36
src/storm/logic/RewardAccumulationEliminationVisitor.cpp

@ -3,6 +3,7 @@
#include "storm/storage/jani/Model.h"
#include "storm/storage/jani/traverser/AssignmentsFinder.h"
#include "storm/storage/jani/expressions/JaniExpressionSubstitutionVisitor.h"
#include "storm/utility/macros.h"
#include "storm/exceptions/UnexpectedException.h"
@ -126,20 +127,33 @@ namespace storm {
}
bool RewardAccumulationEliminationVisitor::canEliminate(storm::logic::RewardAccumulation const& accumulation, boost::optional<std::string> rewardModelName) const {
STORM_LOG_THROW(rewardModelName.is_initialized(), storm::exceptions::InvalidPropertyException, "Unable to find transient variable with for unique reward model.");
storm::jani::AssignmentsFinder::ResultType assignmentKinds;
STORM_LOG_THROW(model.hasGlobalVariable(rewardModelName.get()), storm::exceptions::InvalidPropertyException, "Unable to find transient variable with name " << rewardModelName.get() << ".");
storm::jani::Variable const& transientVar = model.getGlobalVariable(rewardModelName.get());
if (transientVar.getInitExpression().containsVariables() || !storm::utility::isZero(transientVar.getInitExpression().evaluateAsRational())) {
assignmentKinds.hasLocationAssignment = true;
assignmentKinds.hasEdgeAssignment = true;
assignmentKinds.hasEdgeDestinationAssignment = true;
STORM_LOG_THROW(rewardModelName.is_initialized(), storm::exceptions::InvalidPropertyException, "Unable to find transient variable for unique reward model.");
storm::expressions::Expression rewardExpression = model.getRewardModelExpression(rewardModelName.get());
bool hasStateRewards = false;
bool hasActionOrTransitionRewards = false;
auto variablesInRewardExpression = rewardExpression.getVariables();
std::map<storm::expressions::Variable, storm::expressions::Expression> initialSubstitution;
for (auto const& v : variablesInRewardExpression) {
STORM_LOG_ASSERT(model.hasGlobalVariable(v.getName()), "Unable to find global variable " << v.getName() << " occurring in a reward expression.");
auto const& janiVar = model.getGlobalVariable(v.getName());
if (janiVar.hasInitExpression()) {
initialSubstitution.emplace(v, janiVar.getInitExpression());
}
auto assignmentKinds = storm::jani::AssignmentsFinder().find(model, v);
hasActionOrTransitionRewards = hasActionOrTransitionRewards || assignmentKinds.hasEdgeAssignment || assignmentKinds.hasEdgeDestinationAssignment;
hasStateRewards = hasStateRewards || assignmentKinds.hasLocationAssignment;
}
rewardExpression = storm::jani::substituteJaniExpression(rewardExpression, initialSubstitution);
if (rewardExpression.containsVariables() || !storm::utility::isZero(rewardExpression.evaluateAsRational())) {
hasStateRewards = true;
hasActionOrTransitionRewards = true;
}
assignmentKinds = storm::jani::AssignmentsFinder().find(model, transientVar);
if ((assignmentKinds.hasEdgeAssignment || assignmentKinds.hasEdgeDestinationAssignment) && !accumulation.isStepsSet()) {
if (hasActionOrTransitionRewards && !accumulation.isStepsSet()) {
return false;
}
if (assignmentKinds.hasLocationAssignment) {
if (hasStateRewards) {
if (model.isDiscreteTimeModel()) {
if (!accumulation.isExitSet()) {
return false;

8
src/storm/storage/jani/Automaton.cpp

@ -444,9 +444,11 @@ namespace storm {
for (auto& location : this->getLocations()) {
location.substitute(substitution);
}
this->setInitialStatesRestriction(substituteJaniExpression(this->getInitialStatesRestriction(), substitution));
if (hasInitialStatesRestriction()) {
this->setInitialStatesRestriction(substituteJaniExpression(this->getInitialStatesRestriction(), substitution));
}
edges.substitute(substitution);
}
void Automaton::registerTemplateEdge(std::shared_ptr<TemplateEdge> const& te) {

8
src/storm/storage/jani/JSONExporter.cpp

@ -183,7 +183,7 @@ namespace storm {
time = time || (!model.isDeterministicModel() && assignmentKinds.hasLocationAssignment);
exit = exit || assignmentKinds.hasLocationAssignment;
}
storm::jani::substituteJaniExpression(rewardExpression, initialSubstitution);
rewardExpression = storm::jani::substituteJaniExpression(rewardExpression, initialSubstitution);
if (rewardExpression.containsVariables() || !storm::utility::isZero(rewardExpression.evaluateAsRational())) {
steps = true;
time = true;
@ -1118,7 +1118,11 @@ namespace storm {
// Unset model-features that only relate to properties. These are only set if such properties actually exist.
modelFeatures.remove(storm::jani::ModelFeature::StateExitRewards);
if (formulas.empty()) {
jsonStruct["properties"] = modernjson::json(modernjson::json::value_t::array);
return;
}
uint64_t index = 0;
for(auto const& f : formulas) {
modernjson::json propDecl;

20
src/storm/storage/jani/Model.cpp

@ -117,6 +117,10 @@ namespace storm {
ModelType const& Model::getModelType() const {
return modelType;
}
void Model::setModelType(ModelType const& newModelType) {
modelType = newModelType;
}
ModelFeatures const& Model::getModelFeatures() const {
return modelFeatures;
@ -633,6 +637,22 @@ namespace storm {
bool Model::hasConstant(std::string const& name) const {
return constantToIndex.find(name) != constantToIndex.end();
}
void Model::removeConstant(std::string const& name) {
auto pos = constantToIndex.find(name);
if (pos != constantToIndex.end()) {
uint64_t index = pos->second;
constants.erase(constants.begin() + index);
constantToIndex.erase(pos);
for (auto& entry : constantToIndex) {
if(entry.second > index) {
entry.second--;
}
}
}
}
Constant const& Model::getConstant(std::string const& name) const {
auto it = constantToIndex.find(name);

13
src/storm/storage/jani/Model.h

@ -79,7 +79,13 @@ namespace storm {
* Retrieves the type of the model.
*/
ModelType const& getModelType() const;
/*!
* Changes (only) the type declaration of the model. Notice that this operation should be applied with great care, as it may break several algorithms.
* The operation is useful to e.g. make a deterministic model into a non-deterministic one.
*/
void setModelType(ModelType const&);
/*!
* Retrieves the enabled model features
*/
@ -163,6 +169,11 @@ namespace storm {
* Retrieves whether the model has a constant with the given name.
*/
bool hasConstant(std::string const& name) const;
/*!
* Removes (without checks) a constant from the model.
*/
void removeConstant(std::string const& name);
/*!
* Retrieves the constants of the model.

2
src/storm/storage/prism/Program.cpp

@ -1820,6 +1820,8 @@ namespace storm {
std::vector<storm::jani::Property> newProperties;
if (converter.labelsWereRenamed() || converter.rewardModelsWereRenamed()) {
newProperties = converter.applyRenaming(properties);
} else {
newProperties = properties; // Nothing to be done here. Notice that the copy operation is suboptimal.
}
return std::make_pair(janiModel, newProperties);
}

3
src/storm/transformer/SubsystemBuilder.cpp

@ -65,7 +65,6 @@ namespace storm {
result.keptActions = storm::storage::BitVector(originalModel.getTransitionMatrix().getRowCount(), false);
for (auto subsysState : subsystemStates) {
result.newToOldStateIndexMapping.push_back(subsysState);
bool stateHasOneChoiceLeft = false;
for (uint_fast64_t row = subsystemActions.getNextSetIndex(originalModel.getTransitionMatrix().getRowGroupIndices()[subsysState]); row < originalModel.getTransitionMatrix().getRowGroupIndices()[subsysState+1]; row = subsystemActions.getNextSetIndex(row+1)) {
bool allRowEntriesStayInSubsys = true;
for (auto const& entry : originalModel.getTransitionMatrix().getRow(row)) {
@ -74,10 +73,8 @@ namespace storm {
break;
}
}
stateHasOneChoiceLeft |= allRowEntriesStayInSubsys;
result.keptActions.set(row, allRowEntriesStayInSubsys);
}
STORM_LOG_THROW(stateHasOneChoiceLeft, storm::exceptions::InvalidArgumentException, "The subsystem would contain a deadlock state.");
}
// Transform the components of the model

103
src/storm/utility/graph.cpp

@ -1554,9 +1554,56 @@ namespace storm {
return SymbolicGameProb01Result<Type>(maybePlayer1States, maybePlayer2States, player1StrategyBdd, player2StrategyBdd);
}
template<typename T>
void topologicalSortHelper(storm::storage::SparseMatrix<T> const& matrix, uint64_t state, std::vector<uint_fast64_t>& topologicalSort, std::vector<uint_fast64_t>& recursionStack, std::vector<typename storm::storage::SparseMatrix<T>::const_iterator>& iteratorRecursionStack, storm::storage::BitVector& visitedStates) {
if (!visitedStates.get(state)) {
recursionStack.push_back(state);
iteratorRecursionStack.push_back(matrix.begin(state));
recursionStepForward:
while (!recursionStack.empty()) {
uint_fast64_t currentState = recursionStack.back();
typename storm::storage::SparseMatrix<T>::const_iterator successorIterator = iteratorRecursionStack.back();
visitedStates.set(currentState, true);
recursionStepBackward:
for (; successorIterator != matrix.end(currentState); ++successorIterator) {
if (!visitedStates.get(successorIterator->getColumn())) {
// Put unvisited successor on top of our recursion stack and remember that.
recursionStack.push_back(successorIterator->getColumn());
// Also, put initial value for iterator on corresponding recursion stack.
iteratorRecursionStack.push_back(matrix.begin(successorIterator->getColumn()));
goto recursionStepForward;
}
}
topologicalSort.push_back(currentState);
// If we reach this point, we have completed the recursive descent for the current state.
// That is, we need to pop it from the recursion stacks.
recursionStack.pop_back();
iteratorRecursionStack.pop_back();
// If there is at least one state under the current one in our recursion stack, we need
// to restore the topmost state as the current state and jump to the part after the
// original recursive call.
if (recursionStack.size() > 0) {
currentState = recursionStack.back();
successorIterator = iteratorRecursionStack.back();
goto recursionStepBackward;
}
}
}
}
template <typename T>
std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix) {
std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix, std::vector<uint64_t> const& firstStates) {
if (matrix.getRowCount() != matrix.getColumnCount()) {
STORM_LOG_ERROR("Provided matrix is required to be square.");
throw storm::exceptions::InvalidArgumentException() << "Provided matrix is required to be square.";
@ -1576,49 +1623,11 @@ namespace storm {
// Perform a depth-first search over the given transitions and record states in the reverse order they were visited.
storm::storage::BitVector visitedStates(numberOfStates);
for (auto const state : firstStates ) {
topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
}
for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
if (!visitedStates.get(state)) {
recursionStack.push_back(state);
iteratorRecursionStack.push_back(matrix.begin(state));
recursionStepForward:
while (!recursionStack.empty()) {
uint_fast64_t currentState = recursionStack.back();
typename storm::storage::SparseMatrix<T>::const_iterator successorIterator = iteratorRecursionStack.back();
visitedStates.set(currentState, true);
recursionStepBackward:
for (; successorIterator != matrix.end(currentState); ++successorIterator) {
if (!visitedStates.get(successorIterator->getColumn())) {
// Put unvisited successor on top of our recursion stack and remember that.
recursionStack.push_back(successorIterator->getColumn());
// Also, put initial value for iterator on corresponding recursion stack.
iteratorRecursionStack.push_back(matrix.begin(successorIterator->getColumn()));
goto recursionStepForward;
}
}
topologicalSort.push_back(currentState);
// If we reach this point, we have completed the recursive descent for the current state.
// That is, we need to pop it from the recursion stacks.
recursionStack.pop_back();
iteratorRecursionStack.pop_back();
// If there is at least one state under the current one in our recursion stack, we need
// to restore the topmost state as the current state and jump to the part after the
// original recursive call.
if (recursionStack.size() > 0) {
currentState = recursionStack.back();
successorIterator = iteratorRecursionStack.back();
goto recursionStepBackward;
}
}
}
topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
}
return topologicalSort;
@ -1696,7 +1705,7 @@ namespace storm {
template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix<double> const& transitionMatrix, std::vector<uint64_t> const& player1RowGrouping, storm::storage::SparseMatrix<double> const& player1BackwardTransitions, std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction, storm::OptimizationDirection const& player2Direction, storm::abstraction::ExplicitGameStrategyPair* strategyPair, boost::optional<storm::storage::BitVector> const& player1Candidates);
template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<double> const& matrix) ;
template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<double> const& matrix, std::vector<uint64_t> const& firstStates) ;
// Instantiations for storm::RationalNumber.
#ifdef STORM_HAVE_CARL
@ -1752,7 +1761,7 @@ namespace storm {
template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix, std::vector<uint64_t> const& player1RowGrouping, storm::storage::SparseMatrix<storm::RationalNumber> const& player1BackwardTransitions, std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction, storm::OptimizationDirection const& player2Direction, storm::abstraction::ExplicitGameStrategyPair* strategyPair, boost::optional<storm::storage::BitVector> const& player1Candidates);
template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalNumber> const& matrix);
template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalNumber> const& matrix, std::vector<uint64_t> const& firstStates);
// End of instantiations for storm::RationalNumber.
template storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates, storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional<storm::storage::BitVector> const& choiceFilter);
@ -1804,7 +1813,7 @@ namespace storm {
template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::models::sparse::NondeterministicModel<storm::RationalFunction> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalFunction> const& matrix);
template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalFunction> const& matrix, std::vector<uint64_t> const& firstStates);
#endif

2
src/storm/utility/graph.h

@ -683,7 +683,7 @@ namespace storm {
* @return A vector of indices that is a topological sort of the states.
*/
template <typename T>
std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix) ;
std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix, std::vector<uint64_t> const& firstStates = {}) ;
} // namespace graph
} // namespace utility

3
src/storm/utility/shortestPaths.h

@ -235,7 +235,8 @@ namespace storm {
// only non-zero entries (i.e. true transitions) are added to the map
if (probEntry != 0) {
assert(0 < probEntry <= 1);
assert(0 < probEntry);
assert(probEntry <= 1);
stateProbMap.emplace(i, probEntry);
}
}

Loading…
Cancel
Save