Browse Source

special treatment of trivial initial states restriction for JANI (following PRISM) next-state generator

tempestpy_adaptions
dehnert 6 years ago
parent
commit
205ed7f4bf
  1. 61
      src/storm/generator/JaniNextStateGenerator.cpp
  2. 6
      src/storm/storage/jani/Automaton.cpp
  3. 5
      src/storm/storage/jani/Automaton.h
  4. 14
      src/storm/storage/jani/Model.cpp
  5. 6
      src/storm/storage/jani/Model.h

61
src/storm/generator/JaniNextStateGenerator.cpp

@ -171,6 +171,9 @@ namespace storm {
template<typename ValueType, typename StateType> template<typename ValueType, typename StateType>
std::vector<StateType> JaniNextStateGenerator<ValueType, StateType>::getInitialStates(StateToIdCallback const& stateToIdCallback) { std::vector<StateType> JaniNextStateGenerator<ValueType, StateType>::getInitialStates(StateToIdCallback const& stateToIdCallback) {
std::vector<StateType> initialStateIndices;
if (this->model.hasNonTrivialInitialStatesRestriction()) {
// Prepare an SMT solver to enumerate all initial states. // Prepare an SMT solver to enumerate all initial states.
storm::utility::solver::SmtSolverFactory factory; storm::utility::solver::SmtSolverFactory factory;
std::unique_ptr<storm::solver::SmtSolver> solver = factory.create(model.getExpressionManager()); std::unique_ptr<storm::solver::SmtSolver> solver = factory.create(model.getExpressionManager());
@ -182,7 +185,6 @@ namespace storm {
solver->add(model.getInitialStatesExpression(this->parallelAutomata)); solver->add(model.getInitialStatesExpression(this->parallelAutomata));
// Proceed as long as the solver can still enumerate initial states. // Proceed as long as the solver can still enumerate initial states.
std::vector<StateType> initialStateIndices;
while (solver->check() == storm::solver::SmtSolver::CheckResult::Sat) { while (solver->check() == storm::solver::SmtSolver::CheckResult::Sat) {
// Create fresh state. // Create fresh state.
CompressedState initialState(this->variableInformation.getTotalBitOffset(true)); CompressedState initialState(this->variableInformation.getTotalBitOffset(true));
@ -226,6 +228,63 @@ namespace storm {
solver->add(blockingExpression); solver->add(blockingExpression);
} }
STORM_LOG_DEBUG("Enumerated " << initialStateIndices.size() << " initial states using SMT solving.");
} else {
CompressedState initialState(this->variableInformation.getTotalBitOffset(true));
std::vector<int_fast64_t> currentIntegerValues;
currentIntegerValues.reserve(this->variableInformation.integerVariables.size());
for (auto const& variable : this->variableInformation.integerVariables) {
STORM_LOG_THROW(variable.lowerBound <= variable.upperBound, storm::exceptions::InvalidArgumentException, "Expecting variable with non-empty set of possible values.");
currentIntegerValues.emplace_back(0);
initialState.setFromInt(variable.bitOffset, variable.bitWidth, 0);
}
initialStateIndices.emplace_back(stateToIdCallback(initialState));
bool done = false;
while (!done) {
bool changedBooleanVariable = false;
for (auto const& booleanVariable : this->variableInformation.booleanVariables) {
if (initialState.get(booleanVariable.bitOffset)) {
initialState.set(booleanVariable.bitOffset);
changedBooleanVariable = true;
break;
} else {
initialState.set(booleanVariable.bitOffset, false);
}
}
bool changedIntegerVariable = false;
if (changedBooleanVariable) {
initialStateIndices.emplace_back(stateToIdCallback(initialState));
} else {
for (uint64_t integerVariableIndex = 0; integerVariableIndex < this->variableInformation.integerVariables.size(); ++integerVariableIndex) {
auto const& integerVariable = this->variableInformation.integerVariables[integerVariableIndex];
if (currentIntegerValues[integerVariableIndex] < integerVariable.upperBound - integerVariable.lowerBound) {
++currentIntegerValues[integerVariableIndex];
changedIntegerVariable = true;
} else {
currentIntegerValues[integerVariableIndex] = integerVariable.lowerBound;
}
initialState.setFromInt(integerVariable.bitOffset, integerVariable.bitWidth, currentIntegerValues[integerVariableIndex]);
if (changedIntegerVariable) {
break;
}
}
}
if (changedIntegerVariable) {
initialStateIndices.emplace_back(stateToIdCallback(initialState));
}
done = !changedBooleanVariable && !changedIntegerVariable;
}
STORM_LOG_DEBUG("Enumerated " << initialStateIndices.size() << " initial states using brute force enumeration.");
}
return initialStateIndices; return initialStateIndices;
} }

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

@ -286,8 +286,6 @@ namespace storm {
for (uint64_t locationIndex = edge.getSourceLocationIndex() + 1; locationIndex < locationToStartingIndex.size(); ++locationIndex) { for (uint64_t locationIndex = edge.getSourceLocationIndex() + 1; locationIndex < locationToStartingIndex.size(); ++locationIndex) {
++locationToStartingIndex[locationIndex]; ++locationToStartingIndex[locationIndex];
} }
} }
std::vector<Edge>& Automaton::getEdges() { std::vector<Edge>& Automaton::getEdges() {
@ -325,6 +323,10 @@ namespace storm {
return initialStatesRestriction.isInitialized(); return initialStatesRestriction.isInitialized();
} }
bool Automaton::hasNonTrivialInitialStatesRestriction() const {
return this->hasInitialStatesRestriction() && !this->getInitialStatesRestriction().isTrue();
}
storm::expressions::Expression const& Automaton::getInitialStatesRestriction() const { storm::expressions::Expression const& Automaton::getInitialStatesRestriction() const {
return initialStatesRestriction; return initialStatesRestriction;
} }

5
src/storm/storage/jani/Automaton.h

@ -241,6 +241,11 @@ namespace storm {
*/ */
bool hasInitialStatesRestriction() const; bool hasInitialStatesRestriction() const;
/*!
* Retrieves whether there is a non-trivial initial states restriction.
*/
bool hasNonTrivialInitialStatesRestriction() const;
/*! /*!
* Gets the expression restricting the legal initial values of the automaton's variables. * Gets the expression restricting the legal initial values of the automaton's variables.
*/ */

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

@ -939,6 +939,20 @@ namespace storm {
return initialStatesRestriction; return initialStatesRestriction;
} }
bool Model::hasNonTrivialInitialStatesRestriction() const {
if (this->hasInitialStatesRestriction() && !this->getInitialStatesRestriction().isTrue()) {
return true;
} else {
for (auto const& automaton : this->automata) {
if (automaton.hasInitialStatesRestriction() && !automaton.getInitialStatesRestriction().isTrue()) {
return true;
}
}
}
return false;
}
storm::expressions::Expression Model::getInitialStatesExpression() const { storm::expressions::Expression Model::getInitialStatesExpression() const {
std::vector<std::reference_wrapper<storm::jani::Automaton const>> allAutomata; std::vector<std::reference_wrapper<storm::jani::Automaton const>> allAutomata;
for (auto const& automaton : this->getAutomata()) { for (auto const& automaton : this->getAutomata()) {

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

@ -357,6 +357,12 @@ namespace storm {
*/ */
bool hasInitialStatesRestriction() const; bool hasInitialStatesRestriction() const;
/*!
* Retrieves whether there is a non-trivial initial states restriction in the model or any of the contained
* automata.
*/
bool hasNonTrivialInitialStatesRestriction() const;
/*! /*!
* Sets the expression restricting the legal initial values of the global variables. * Sets the expression restricting the legal initial values of the global variables.
*/ */

Loading…
Cancel
Save