24 changed files with 663 additions and 216 deletions
-
261src/generator/JaniNextStateGenerator.cpp
-
134src/generator/JaniNextStateGenerator.h
-
47src/generator/PrismNextStateGenerator.cpp
-
73src/generator/VariableInformation.cpp
-
35src/generator/VariableInformation.h
-
7src/storage/jani/Automaton.cpp
-
5src/storage/jani/Automaton.h
-
4src/storage/jani/BoundedIntegerVariable.cpp
-
5src/storage/jani/BoundedIntegerVariable.h
-
92src/storage/jani/CompositionInformationVisitor.cpp
-
60src/storage/jani/CompositionInformationVisitor.h
-
1src/storage/jani/CompositionVisitor.h
-
3src/storage/jani/Compositions.h
-
14src/storage/jani/EdgeDestination.cpp
-
6src/storage/jani/EdgeDestination.h
-
13src/storage/jani/Model.cpp
-
5src/storage/jani/Model.h
-
4src/storage/prism/IntegerVariable.cpp
-
7src/storage/prism/IntegerVariable.h
-
19src/storage/prism/Module.cpp
-
16src/storage/prism/Module.h
-
34src/storage/prism/Program.cpp
-
14src/storage/prism/Program.h
-
8src/storage/prism/Update.cpp
@ -1,89 +1,172 @@ |
|||||
//#include "src/generator/JaniNextStateGenerator.h"
|
|
||||
//
|
|
||||
//#include "src/models/sparse/StateLabeling.h"
|
|
||||
//
|
|
||||
//#include "src/storage/expressions/SimpleValuation.h"
|
|
||||
//
|
|
||||
//#include "src/utility/constants.h"
|
|
||||
//#include "src/utility/macros.h"
|
|
||||
//#include "src/exceptions/InvalidSettingsException.h"
|
|
||||
//#include "src/exceptions/WrongFormatException.h"
|
|
||||
//
|
|
||||
//namespace storm {
|
|
||||
// namespace generator {
|
|
||||
//
|
|
||||
// template<typename ValueType, typename StateType>
|
|
||||
// JaniNextStateGenerator<ValueType, StateType>::JaniNextStateGenerator(storm::jani::Model const& model, NextStateGeneratorOptions const& options) : NextStateGenerator<ValueType, StateType>(options), model(model.substituteConstants()), variableInformation(this->model), evaluator(this->model.getManager()), state(nullptr), comparator() {
|
|
||||
// STORM_LOG_THROW(!this->model.hasDefaultComposition(), storm::exceptions::WrongFormatException, "The explicit next-state generator currently does not support custom system compositions.");
|
|
||||
// STORM_LOG_THROW(!this->options.isBuildAllRewardModelsSet() && this->options.getRewardModelNames().empty(), storm::exceptions::InvalidSettingsException, "The explicit next-state generator currently does not support building reward models.");
|
|
||||
//
|
|
||||
// // If there are terminal states we need to handle, we now need to translate all labels to expressions.
|
|
||||
// if (this->options.hasTerminalStates()) {
|
|
||||
// for (auto const& expressionOrLabelAndBool : this->options.getTerminalStates()) {
|
|
||||
// if (expressionOrLabelAndBool.first.isExpression()) {
|
|
||||
// terminalStates.push_back(std::make_pair(expressionOrLabelAndBool.first.getExpression(), expressionOrLabelAndBool.second));
|
|
||||
// } else {
|
|
||||
// STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Cannot make label terminal for JANI models.");
|
|
||||
// }
|
|
||||
// }
|
|
||||
// }
|
|
||||
// }
|
|
||||
//
|
|
||||
// template<typename ValueType, typename StateType>
|
|
||||
// uint64_t JaniNextStateGenerator<ValueType, StateType>::getStateSize() const {
|
|
||||
// return variableInformation.getTotalBitOffset(true);
|
|
||||
// }
|
|
||||
//
|
|
||||
// template<typename ValueType, typename StateType>
|
|
||||
// ModelType JaniNextStateGenerator<ValueType, StateType>::getModelType() const {
|
|
||||
// switch (model.getModelType()) {
|
|
||||
// case storm::jani::ModelType::DTMC: return ModelType::DTMC;
|
|
||||
// case storm::jani::ModelType::CTMC: return ModelType::CTMC;
|
|
||||
// case storm::jani::ModelType::MDP: return ModelType::MDP;
|
|
||||
// case storm::jani::ModelType::MA: return ModelType::MA;
|
|
||||
// default:
|
|
||||
// STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Invalid model type.");
|
|
||||
// }
|
|
||||
// }
|
|
||||
//
|
|
||||
// template<typename ValueType, typename StateType>
|
|
||||
// bool JaniNextStateGenerator<ValueType, StateType>::isDeterministicModel() const {
|
|
||||
// return model.isDeterministicModel();
|
|
||||
// }
|
|
||||
//
|
|
||||
// template<typename ValueType, typename StateType>
|
|
||||
// std::vector<StateType> JaniNextStateGenerator<ValueType, StateType>::getInitialStates(StateToIdCallback const& stateToIdCallback) {
|
|
||||
// // FIXME: This only works for models with exactly one initial state. We should make this more general.
|
|
||||
// CompressedState initialState(variableInformation.getTotalBitOffset());
|
|
||||
//
|
|
||||
// // We need to initialize the values of the variables to their initial value.
|
|
||||
// for (auto const& booleanVariable : variableInformation.booleanVariables) {
|
|
||||
// initialState.set(booleanVariable.bitOffset, booleanVariable.initialValue);
|
|
||||
// }
|
|
||||
// for (auto const& integerVariable : variableInformation.integerVariables) {
|
|
||||
// initialState.setFromInt(integerVariable.bitOffset, integerVariable.bitWidth, static_cast<uint_fast64_t>(integerVariable.initialValue - integerVariable.lowerBound));
|
|
||||
// }
|
|
||||
//
|
|
||||
// // Register initial state and return it.
|
|
||||
// StateType id = stateToIdCallback(initialState);
|
|
||||
// return {id};
|
|
||||
// }
|
|
||||
//
|
|
||||
// template<typename ValueType, typename StateType>
|
|
||||
// void JaniNextStateGenerator<ValueType, StateType>::load(CompressedState const& state) {
|
|
||||
// // Since almost all subsequent operations are based on the evaluator, we load the state into it now.
|
|
||||
// unpackStateIntoEvaluator(state, variableInformation, evaluator);
|
|
||||
//
|
|
||||
// // Also, we need to store a pointer to the state itself, because we need to be able to access it when expanding it.
|
|
||||
// this->state = &state;
|
|
||||
// }
|
|
||||
//
|
|
||||
// template<typename ValueType, typename StateType>
|
|
||||
// bool JaniNextStateGenerator<ValueType, StateType>::satisfies(storm::expressions::Expression const& expression) const {
|
|
||||
// if (expression.isTrue()) {
|
|
||||
// return true;
|
|
||||
// }
|
|
||||
// return evaluator.asBool(expression);
|
|
||||
// }
|
|
||||
// }
|
|
||||
//}
|
|
||||
|
#include "src/generator/JaniNextStateGenerator.h"
|
||||
|
|
||||
|
#include "src/models/sparse/StateLabeling.h"
|
||||
|
|
||||
|
#include "src/storage/expressions/SimpleValuation.h"
|
||||
|
|
||||
|
#include "src/solver/SmtSolver.h"
|
||||
|
|
||||
|
#include "src/utility/constants.h"
|
||||
|
#include "src/utility/macros.h"
|
||||
|
#include "src/utility/solver.h"
|
||||
|
#include "src/exceptions/InvalidSettingsException.h"
|
||||
|
#include "src/exceptions/WrongFormatException.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace generator { |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
JaniNextStateGenerator<ValueType, StateType>::JaniNextStateGenerator(storm::jani::Model const& model, NextStateGeneratorOptions const& options) : JaniNextStateGenerator(model.substituteConstants(), options, false) { |
||||
|
// Intentionally left empty.
|
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
JaniNextStateGenerator<ValueType, StateType>::JaniNextStateGenerator(storm::jani::Model const& model, NextStateGeneratorOptions const& options, bool flag) : NextStateGenerator<ValueType, StateType>(model.getExpressionManager(), VariableInformation(model), options), model(model) { |
||||
|
STORM_LOG_THROW(!this->model.hasDefaultComposition(), storm::exceptions::WrongFormatException, "The explicit next-state generator currently does not support custom system compositions."); |
||||
|
STORM_LOG_THROW(!this->options.isBuildAllRewardModelsSet() && this->options.getRewardModelNames().empty(), storm::exceptions::InvalidSettingsException, "The explicit next-state generator currently does not support building reward models."); |
||||
|
|
||||
|
// If there are terminal states we need to handle, we now need to translate all labels to expressions.
|
||||
|
if (this->options.hasTerminalStates()) { |
||||
|
for (auto const& expressionOrLabelAndBool : this->options.getTerminalStates()) { |
||||
|
if (expressionOrLabelAndBool.first.isExpression()) { |
||||
|
this->terminalStates.push_back(std::make_pair(expressionOrLabelAndBool.first.getExpression(), expressionOrLabelAndBool.second)); |
||||
|
} else { |
||||
|
STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Cannot make label terminal for JANI models."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
ModelType JaniNextStateGenerator<ValueType, StateType>::getModelType() const { |
||||
|
switch (model.getModelType()) { |
||||
|
case storm::jani::ModelType::DTMC: return ModelType::DTMC; |
||||
|
case storm::jani::ModelType::CTMC: return ModelType::CTMC; |
||||
|
case storm::jani::ModelType::MDP: return ModelType::MDP; |
||||
|
case storm::jani::ModelType::MA: return ModelType::MA; |
||||
|
default: |
||||
|
STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Invalid model type."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
bool JaniNextStateGenerator<ValueType, StateType>::isDeterministicModel() const { |
||||
|
return model.isDeterministicModel(); |
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
std::vector<StateType> JaniNextStateGenerator<ValueType, StateType>::getInitialStates(StateToIdCallback const& stateToIdCallback) { |
||||
|
// Prepare an SMT solver to enumerate all initial states.
|
||||
|
storm::utility::solver::SmtSolverFactory factory; |
||||
|
std::unique_ptr<storm::solver::SmtSolver> solver = factory.create(model.getExpressionManager()); |
||||
|
|
||||
|
std::vector<storm::expressions::Expression> rangeExpressions = model.getAllRangeExpressions(); |
||||
|
for (auto const& expression : rangeExpressions) { |
||||
|
solver->add(expression); |
||||
|
} |
||||
|
solver->add(model.getInitialStatesExpression(true)); |
||||
|
|
||||
|
// Proceed ss long as the solver can still enumerate initial states.
|
||||
|
std::vector<StateType> initialStateIndices; |
||||
|
while (solver->check() == storm::solver::SmtSolver::CheckResult::Sat) { |
||||
|
// Create fresh state.
|
||||
|
CompressedState initialState(this->variableInformation.getTotalBitOffset()); |
||||
|
|
||||
|
// Read variable assignment from the solution of the solver. Also, create an expression we can use to
|
||||
|
// prevent the variable assignment from being enumerated again.
|
||||
|
storm::expressions::Expression blockingExpression; |
||||
|
std::shared_ptr<storm::solver::SmtSolver::ModelReference> model = solver->getModel(); |
||||
|
for (auto const& booleanVariable : this->variableInformation.booleanVariables) { |
||||
|
bool variableValue = model->getBooleanValue(booleanVariable.variable); |
||||
|
storm::expressions::Expression localBlockingExpression = variableValue ? !booleanVariable.variable : booleanVariable.variable; |
||||
|
blockingExpression = blockingExpression.isInitialized() ? blockingExpression || localBlockingExpression : localBlockingExpression; |
||||
|
initialState.set(booleanVariable.bitOffset, variableValue); |
||||
|
} |
||||
|
for (auto const& integerVariable : this->variableInformation.integerVariables) { |
||||
|
int_fast64_t variableValue = model->getIntegerValue(integerVariable.variable); |
||||
|
storm::expressions::Expression localBlockingExpression = integerVariable.variable != model->getManager().integer(variableValue); |
||||
|
blockingExpression = blockingExpression.isInitialized() ? blockingExpression || localBlockingExpression : localBlockingExpression; |
||||
|
initialState.setFromInt(integerVariable.bitOffset, integerVariable.bitWidth, static_cast<uint_fast64_t>(variableValue - integerVariable.lowerBound)); |
||||
|
} |
||||
|
|
||||
|
// Register initial state and return it.
|
||||
|
StateType id = stateToIdCallback(initialState); |
||||
|
initialStateIndices.push_back(id); |
||||
|
|
||||
|
// Block the current initial state to search for the next one.
|
||||
|
solver->add(blockingExpression); |
||||
|
} |
||||
|
|
||||
|
return initialStateIndices; |
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
CompressedState JaniNextStateGenerator<ValueType, StateType>::applyUpdate(CompressedState const& state, storm::jani::EdgeDestination const& destination) { |
||||
|
CompressedState newState(state); |
||||
|
|
||||
|
auto assignmentIt = destination.getAssignments().begin(); |
||||
|
auto assignmentIte = destination.getAssignments().end(); |
||||
|
|
||||
|
// Iterate over all boolean assignments and carry them out.
|
||||
|
auto boolIt = this->variableInformation.booleanVariables.begin(); |
||||
|
for (; assignmentIt != assignmentIte && assignmentIt->getAssignedExpression().hasBooleanType(); ++assignmentIt) { |
||||
|
while (assignmentIt->getExpressionVariable() != boolIt->variable) { |
||||
|
++boolIt; |
||||
|
} |
||||
|
newState.set(boolIt->bitOffset, this->evaluator.asBool(assignmentIt->getExpressionVariable())); |
||||
|
} |
||||
|
|
||||
|
// Iterate over all integer assignments and carry them out.
|
||||
|
auto integerIt = this->variableInformation.integerVariables.begin(); |
||||
|
for (; assignmentIt != assignmentIte && assignmentIt->getAssignedExpression().hasIntegerType(); ++assignmentIt) { |
||||
|
while (assignmentIt->getExpressionVariable() != integerIt->variable) { |
||||
|
++integerIt; |
||||
|
} |
||||
|
int_fast64_t assignedValue = this->evaluator.asInt(assignmentIt->getAssignedExpression()); |
||||
|
STORM_LOG_THROW(assignedValue <= integerIt->upperBound, storm::exceptions::WrongFormatException, "The update " << assignmentIt->getExpressionVariable().getName() << " := " << assignmentIt->getAssignedExpression() << " leads to an out-of-bounds value (" << assignedValue << ") for the variable '" << assignmentIt->getExpressionVariable().getName() << "'."); |
||||
|
newState.setFromInt(integerIt->bitOffset, integerIt->bitWidth, assignedValue - integerIt->lowerBound); |
||||
|
STORM_LOG_ASSERT(static_cast<int_fast64_t>(newState.getAsInt(integerIt->bitOffset, integerIt->bitWidth)) + integerIt->lowerBound == assignedValue, "Writing to the bit vector bucket failed (read " << newState.getAsInt(integerIt->bitOffset, integerIt->bitWidth) << " but wrote " << assignedValue << ")."); |
||||
|
} |
||||
|
|
||||
|
// Check that we processed all assignments.
|
||||
|
STORM_LOG_ASSERT(assignmentIt == assignmentIte, "Not all assignments were consumed."); |
||||
|
|
||||
|
return newState; |
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
StateBehavior<ValueType, StateType> JaniNextStateGenerator<ValueType, StateType>::expand(StateToIdCallback const& stateToIdCallback) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
std::vector<Choice<ValueType>> JaniNextStateGenerator<ValueType, StateType>::getSilentActionChoices(CompressedState const& state, StateToIdCallback stateToIdCallback) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
std::vector<Choice<ValueType>> JaniNextStateGenerator<ValueType, StateType>::getNonsilentActionChoices(CompressedState const& state, StateToIdCallback stateToIdCallback) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
std::size_t JaniNextStateGenerator<ValueType, StateType>::getNumberOfRewardModels() const { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
RewardModelInformation JaniNextStateGenerator<ValueType, StateType>::getRewardModelInformation(uint64_t const& index) const { |
||||
|
STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Cannot retrieve reward model information."); |
||||
|
return RewardModelInformation("", false, false, false); |
||||
|
} |
||||
|
|
||||
|
template<typename ValueType, typename StateType> |
||||
|
storm::models::sparse::StateLabeling JaniNextStateGenerator<ValueType, StateType>::label(storm::storage::BitVectorHashMap<StateType> const& states, std::vector<StateType> const& initialStateIndices) { |
||||
|
return NextStateGenerator<ValueType, StateType>::label(states, initialStateIndices, {}); |
||||
|
} |
||||
|
|
||||
|
template class JaniNextStateGenerator<double>; |
||||
|
template class JaniNextStateGenerator<storm::RationalFunction>; |
||||
|
|
||||
|
} |
||||
|
} |
@ -1,68 +1,66 @@ |
|||||
//#pragma once |
|
||||
// |
|
||||
//#include "src/generator/NextStateGenerator.h" |
|
||||
//#include "src/generator/VariableInformation.h" |
|
||||
// |
|
||||
//#include "src/storage/jani/Model.h" |
|
||||
//#include "src/storage/expressions/ExpressionEvaluator.h" |
|
||||
// |
|
||||
//#include "src/utility/ConstantsComparator.h" |
|
||||
// |
|
||||
//namespace storm { |
|
||||
// namespace generator { |
|
||||
// |
|
||||
// template<typename ValueType, typename StateType = uint32_t> |
|
||||
// class JaniNextStateGenerator : public NextStateGenerator<ValueType, StateType> { |
|
||||
// public: |
|
||||
// typedef typename NextStateGenerator<ValueType, StateType>::StateToIdCallback StateToIdCallback; |
|
||||
// |
|
||||
// JaniNextStateGenerator(storm::jani::Model const& model, NextStateGeneratorOptions const& options = NextStateGeneratorOptions()); |
|
||||
// |
|
||||
// virtual uint64_t getStateSize() const override; |
|
||||
// virtual ModelType getModelType() const override; |
|
||||
// virtual bool isDeterministicModel() const override; |
|
||||
// virtual std::vector<StateType> getInitialStates(StateToIdCallback const& stateToIdCallback) override; |
|
||||
// |
|
||||
// virtual void load(CompressedState const& state) override; |
|
||||
// virtual StateBehavior<ValueType, StateType> expand(StateToIdCallback const& stateToIdCallback) override; |
|
||||
// virtual bool satisfies(storm::expressions::Expression const& expression) const override; |
|
||||
// |
|
||||
// virtual std::size_t getNumberOfRewardModels() const override; |
|
||||
// virtual RewardModelInformation getRewardModelInformation(uint64_t const& index) const override; |
|
||||
// |
|
||||
// virtual storm::expressions::SimpleValuation toValuation(CompressedState const& state) const override; |
|
||||
// |
|
||||
// virtual storm::models::sparse::StateLabeling label(storm::storage::BitVectorHashMap<StateType> const& states, std::vector<StateType> const& initialStateIndices = {}) override; |
|
||||
// |
|
||||
// private: |
|
||||
// /*! |
|
||||
// * Applies an update to the state currently loaded into the evaluator and applies the resulting values to |
|
||||
// * the given compressed state. |
|
||||
// * @params state The state to which to apply the new values. |
|
||||
// * @params update The update to apply. |
|
||||
// * @return The resulting state. |
|
||||
// */ |
|
||||
// CompressedState applyUpdate(CompressedState const& state, storm::jani::EdgeDestination const& update); |
|
||||
// |
|
||||
// /*! |
|
||||
// * Retrieves all choices labeled with the silent action possible from the given state. |
|
||||
// * |
|
||||
// * @param state The state for which to retrieve the silent choices. |
|
||||
// * @return The silent action choices of the state. |
|
||||
// */ |
|
||||
// std::vector<Choice<ValueType>> getSilentActionChoices(CompressedState const& state, StateToIdCallback stateToIdCallback); |
|
||||
// |
|
||||
// /*! |
|
||||
// * Retrieves all choices labeled with some non-silent action possible from the given state. |
|
||||
// * |
|
||||
// * @param state The state for which to retrieve the non-silent choices. |
|
||||
// * @return The non-silent action choices of the state. |
|
||||
// */ |
|
||||
// std::vector<Choice<ValueType>> getNonsilentActionChoices(CompressedState const& state, StateToIdCallback stateToIdCallback); |
|
||||
// |
|
||||
// // The model used for the generation of next states. |
|
||||
// storm::jani::Model model; |
|
||||
// }; |
|
||||
// |
|
||||
// } |
|
||||
//} |
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "src/generator/NextStateGenerator.h" |
||||
|
|
||||
|
#include "src/storage/jani/Model.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace generator { |
||||
|
|
||||
|
template<typename ValueType, typename StateType = uint32_t> |
||||
|
class JaniNextStateGenerator : public NextStateGenerator<ValueType, StateType> { |
||||
|
public: |
||||
|
typedef typename NextStateGenerator<ValueType, StateType>::StateToIdCallback StateToIdCallback; |
||||
|
|
||||
|
JaniNextStateGenerator(storm::jani::Model const& model, NextStateGeneratorOptions const& options = NextStateGeneratorOptions()); |
||||
|
|
||||
|
virtual ModelType getModelType() const override; |
||||
|
virtual bool isDeterministicModel() const override; |
||||
|
virtual std::vector<StateType> getInitialStates(StateToIdCallback const& stateToIdCallback) override; |
||||
|
|
||||
|
virtual StateBehavior<ValueType, StateType> expand(StateToIdCallback const& stateToIdCallback) override; |
||||
|
|
||||
|
virtual std::size_t getNumberOfRewardModels() const override; |
||||
|
virtual RewardModelInformation getRewardModelInformation(uint64_t const& index) const override; |
||||
|
|
||||
|
virtual storm::models::sparse::StateLabeling label(storm::storage::BitVectorHashMap<StateType> const& states, std::vector<StateType> const& initialStateIndices = {}) override; |
||||
|
|
||||
|
private: |
||||
|
/*! |
||||
|
* A delegate constructor that is used to preprocess the model before the constructor of the superclass is |
||||
|
* being called. The last argument is only present to distinguish the signature of this constructor from the |
||||
|
* public one. |
||||
|
*/ |
||||
|
JaniNextStateGenerator(storm::jani::Model const& model, NextStateGeneratorOptions const& options, bool flag); |
||||
|
|
||||
|
/*! |
||||
|
* Applies an update to the state currently loaded into the evaluator and applies the resulting values to |
||||
|
* the given compressed state. |
||||
|
* @params state The state to which to apply the new values. |
||||
|
* @params update The update to apply. |
||||
|
* @return The resulting state. |
||||
|
*/ |
||||
|
CompressedState applyUpdate(CompressedState const& state, storm::jani::EdgeDestination const& update); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves all choices labeled with the silent action possible from the given state. |
||||
|
* |
||||
|
* @param state The state for which to retrieve the silent choices. |
||||
|
* @return The silent action choices of the state. |
||||
|
*/ |
||||
|
std::vector<Choice<ValueType>> getSilentActionChoices(CompressedState const& state, StateToIdCallback stateToIdCallback); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves all choices labeled with some non-silent action possible from the given state. |
||||
|
* |
||||
|
* @param state The state for which to retrieve the non-silent choices. |
||||
|
* @return The non-silent action choices of the state. |
||||
|
*/ |
||||
|
std::vector<Choice<ValueType>> getNonsilentActionChoices(CompressedState const& state, StateToIdCallback stateToIdCallback); |
||||
|
|
||||
|
// The model used for the generation of next states. |
||||
|
storm::jani::Model model; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
@ -1,77 +1,92 @@ |
|||||
#include "src/generator/VariableInformation.h"
|
#include "src/generator/VariableInformation.h"
|
||||
|
|
||||
|
#include "src/storage/prism/Program.h"
|
||||
|
#include "src/storage/jani/Model.h"
|
||||
|
|
||||
#include "src/utility/macros.h"
|
#include "src/utility/macros.h"
|
||||
#include "src/exceptions/InvalidArgumentException.h"
|
#include "src/exceptions/InvalidArgumentException.h"
|
||||
|
|
||||
namespace storm { |
namespace storm { |
||||
namespace generator { |
namespace generator { |
||||
|
|
||||
BooleanVariableInformation::BooleanVariableInformation(storm::expressions::Variable const& variable, bool initialValue, uint_fast64_t bitOffset) : variable(variable), initialValue(initialValue), bitOffset(bitOffset) { |
|
||||
|
BooleanVariableInformation::BooleanVariableInformation(storm::expressions::Variable const& variable, uint_fast64_t bitOffset) : variable(variable), bitOffset(bitOffset) { |
||||
// Intentionally left empty.
|
// Intentionally left empty.
|
||||
} |
} |
||||
|
|
||||
IntegerVariableInformation::IntegerVariableInformation(storm::expressions::Variable const& variable, int_fast64_t initialValue, int_fast64_t lowerBound, int_fast64_t upperBound, uint_fast64_t bitOffset, uint_fast64_t bitWidth) : variable(variable), initialValue(initialValue), lowerBound(lowerBound), upperBound(upperBound), bitOffset(bitOffset), bitWidth(bitWidth) { |
|
||||
|
IntegerVariableInformation::IntegerVariableInformation(storm::expressions::Variable const& variable, int_fast64_t lowerBound, int_fast64_t upperBound, uint_fast64_t bitOffset, uint_fast64_t bitWidth) : variable(variable), lowerBound(lowerBound), upperBound(upperBound), bitOffset(bitOffset), bitWidth(bitWidth) { |
||||
// Intentionally left empty.
|
// Intentionally left empty.
|
||||
} |
} |
||||
|
|
||||
VariableInformation::VariableInformation(storm::prism::Program const& program) : totalBitOffset(0) { |
VariableInformation::VariableInformation(storm::prism::Program const& program) : totalBitOffset(0) { |
||||
for (auto const& booleanVariable : program.getGlobalBooleanVariables()) { |
for (auto const& booleanVariable : program.getGlobalBooleanVariables()) { |
||||
booleanVariables.emplace_back(booleanVariable.getExpressionVariable(), booleanVariable.getInitialValueExpression().evaluateAsBool(), totalBitOffset); |
|
||||
|
booleanVariables.emplace_back(booleanVariable.getExpressionVariable(), totalBitOffset); |
||||
++totalBitOffset; |
++totalBitOffset; |
||||
booleanVariableToIndexMap[booleanVariable.getExpressionVariable()] = booleanVariables.size() - 1; |
|
||||
} |
} |
||||
for (auto const& integerVariable : program.getGlobalIntegerVariables()) { |
for (auto const& integerVariable : program.getGlobalIntegerVariables()) { |
||||
int_fast64_t lowerBound = integerVariable.getLowerBoundExpression().evaluateAsInt(); |
int_fast64_t lowerBound = integerVariable.getLowerBoundExpression().evaluateAsInt(); |
||||
int_fast64_t upperBound = integerVariable.getUpperBoundExpression().evaluateAsInt(); |
int_fast64_t upperBound = integerVariable.getUpperBoundExpression().evaluateAsInt(); |
||||
uint_fast64_t bitwidth = static_cast<uint_fast64_t>(std::ceil(std::log2(upperBound - lowerBound + 1))); |
uint_fast64_t bitwidth = static_cast<uint_fast64_t>(std::ceil(std::log2(upperBound - lowerBound + 1))); |
||||
integerVariables.emplace_back(integerVariable.getExpressionVariable(), integerVariable.getInitialValueExpression().evaluateAsInt(), lowerBound, upperBound, totalBitOffset, bitwidth); |
|
||||
|
integerVariables.emplace_back(integerVariable.getExpressionVariable(), lowerBound, upperBound, totalBitOffset, bitwidth); |
||||
totalBitOffset += bitwidth; |
totalBitOffset += bitwidth; |
||||
integerVariableToIndexMap[integerVariable.getExpressionVariable()] = integerVariables.size() - 1; |
|
||||
} |
} |
||||
for (auto const& module : program.getModules()) { |
for (auto const& module : program.getModules()) { |
||||
for (auto const& booleanVariable : module.getBooleanVariables()) { |
for (auto const& booleanVariable : module.getBooleanVariables()) { |
||||
booleanVariables.emplace_back(booleanVariable.getExpressionVariable(), booleanVariable.getInitialValueExpression().evaluateAsBool(), totalBitOffset); |
|
||||
|
booleanVariables.emplace_back(booleanVariable.getExpressionVariable(), totalBitOffset); |
||||
++totalBitOffset; |
++totalBitOffset; |
||||
booleanVariableToIndexMap[booleanVariable.getExpressionVariable()] = booleanVariables.size() - 1; |
|
||||
} |
} |
||||
for (auto const& integerVariable : module.getIntegerVariables()) { |
for (auto const& integerVariable : module.getIntegerVariables()) { |
||||
int_fast64_t lowerBound = integerVariable.getLowerBoundExpression().evaluateAsInt(); |
int_fast64_t lowerBound = integerVariable.getLowerBoundExpression().evaluateAsInt(); |
||||
int_fast64_t upperBound = integerVariable.getUpperBoundExpression().evaluateAsInt(); |
int_fast64_t upperBound = integerVariable.getUpperBoundExpression().evaluateAsInt(); |
||||
uint_fast64_t bitwidth = static_cast<uint_fast64_t>(std::ceil(std::log2(upperBound - lowerBound + 1))); |
uint_fast64_t bitwidth = static_cast<uint_fast64_t>(std::ceil(std::log2(upperBound - lowerBound + 1))); |
||||
integerVariables.emplace_back(integerVariable.getExpressionVariable(), integerVariable.getInitialValueExpression().evaluateAsInt(), lowerBound, upperBound, totalBitOffset, bitwidth); |
|
||||
|
integerVariables.emplace_back(integerVariable.getExpressionVariable(), lowerBound, upperBound, totalBitOffset, bitwidth); |
||||
totalBitOffset += bitwidth; |
totalBitOffset += bitwidth; |
||||
integerVariableToIndexMap[integerVariable.getExpressionVariable()] = integerVariables.size() - 1; |
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
sortVariables(); |
||||
} |
} |
||||
|
|
||||
uint_fast64_t VariableInformation::getTotalBitOffset(bool roundTo64Bit) const { |
|
||||
uint_fast64_t result = totalBitOffset; |
|
||||
if (roundTo64Bit) { |
|
||||
result = ((result >> 6) + 1) << 6; |
|
||||
|
VariableInformation::VariableInformation(storm::jani::Model const& model) { |
||||
|
for (auto const& variable : model.getGlobalVariables().getBooleanVariables()) { |
||||
|
booleanVariables.emplace_back(variable.getExpressionVariable(), totalBitOffset); |
||||
|
++totalBitOffset; |
||||
} |
} |
||||
return result; |
|
||||
|
for (auto const& variable : model.getGlobalVariables().getBoundedIntegerVariables()) { |
||||
|
int_fast64_t lowerBound = variable.getLowerBound().evaluateAsInt(); |
||||
|
int_fast64_t upperBound = variable.getUpperBound().evaluateAsInt(); |
||||
|
uint_fast64_t bitwidth = static_cast<uint_fast64_t>(std::ceil(std::log2(upperBound - lowerBound + 1))); |
||||
|
integerVariables.emplace_back(variable.getExpressionVariable(), lowerBound, upperBound, totalBitOffset, bitwidth); |
||||
|
totalBitOffset += bitwidth; |
||||
} |
} |
||||
|
|
||||
uint_fast64_t VariableInformation::getBitOffset(storm::expressions::Variable const& variable) const { |
|
||||
auto const& booleanIndex = booleanVariableToIndexMap.find(variable); |
|
||||
if (booleanIndex != booleanVariableToIndexMap.end()) { |
|
||||
return booleanVariables[booleanIndex->second].bitOffset; |
|
||||
|
for (auto const& automaton : model.getAutomata()) { |
||||
|
for (auto const& variable : automaton.getVariables().getBooleanVariables()) { |
||||
|
booleanVariables.emplace_back(variable.getExpressionVariable(), totalBitOffset); |
||||
|
++totalBitOffset; |
||||
} |
} |
||||
auto const& integerIndex = integerVariableToIndexMap.find(variable); |
|
||||
if (integerIndex != integerVariableToIndexMap.end()) { |
|
||||
return integerVariables[integerIndex->second].bitOffset; |
|
||||
|
for (auto const& variable : automaton.getVariables().getBoundedIntegerVariables()) { |
||||
|
int_fast64_t lowerBound = variable.getLowerBound().evaluateAsInt(); |
||||
|
int_fast64_t upperBound = variable.getUpperBound().evaluateAsInt(); |
||||
|
uint_fast64_t bitwidth = static_cast<uint_fast64_t>(std::ceil(std::log2(upperBound - lowerBound + 1))); |
||||
|
integerVariables.emplace_back(variable.getExpressionVariable(), lowerBound, upperBound, totalBitOffset, bitwidth); |
||||
|
totalBitOffset += bitwidth; |
||||
} |
} |
||||
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Cannot look-up bit index of unknown variable."); |
|
||||
} |
} |
||||
|
|
||||
uint_fast64_t VariableInformation::getBitWidth(storm::expressions::Variable const& variable) const { |
|
||||
auto const& integerIndex = integerVariableToIndexMap.find(variable); |
|
||||
if (integerIndex != integerVariableToIndexMap.end()) { |
|
||||
return integerVariables[integerIndex->second].bitWidth; |
|
||||
|
sortVariables(); |
||||
} |
} |
||||
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Cannot look-up bit width of unknown variable."); |
|
||||
|
|
||||
|
uint_fast64_t VariableInformation::getTotalBitOffset(bool roundTo64Bit) const { |
||||
|
uint_fast64_t result = totalBitOffset; |
||||
|
if (roundTo64Bit) { |
||||
|
result = ((result >> 6) + 1) << 6; |
||||
|
} |
||||
|
return result; |
||||
} |
} |
||||
|
|
||||
|
void VariableInformation::sortVariables() { |
||||
|
// Sort the variables so we can make some assumptions when iterating over them (in the next-state generators).
|
||||
|
std::sort(booleanVariables.begin(), booleanVariables.end(), [] (BooleanVariableInformation const& a, BooleanVariableInformation const& b) { return a.variable < b.variable; } ); |
||||
|
std::sort(integerVariables.begin(), integerVariables.end(), [] (IntegerVariableInformation const& a, IntegerVariableInformation const& b) { return a.variable < b.variable; }); |
||||
|
} |
||||
} |
} |
||||
} |
} |
@ -0,0 +1,92 @@ |
|||||
|
#include "src/storage/jani/CompositionInformationVisitor.h"
|
||||
|
|
||||
|
#include "src/storage/jani/Model.h"
|
||||
|
#include "src/storage/jani/Compositions.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace jani { |
||||
|
|
||||
|
CompositionInformation::CompositionInformation(std::map<std::string, uint64_t> const& automatonNameToMultiplicity, std::set<std::string> const& nonsilentActions, bool containsRenameComposition, bool containsRestrictedParallelComposition) : automatonNameToMultiplicity(automatonNameToMultiplicity), nonsilentActions(nonsilentActions), renameComposition(containsRenameComposition), restrictedParallelComposition(containsRestrictedParallelComposition) { |
||||
|
// Intentionally left empty.
|
||||
|
} |
||||
|
|
||||
|
void CompositionInformation::increaseAutomatonMultiplicity(std::string const& automatonName, uint64_t count) { |
||||
|
automatonNameToMultiplicity[automatonName] += count; |
||||
|
} |
||||
|
|
||||
|
void CompositionInformation::addNonsilentAction(std::string const& actionName) { |
||||
|
// FIXME
|
||||
|
} |
||||
|
|
||||
|
std::set<std::string> const& CompositionInformation::getNonsilentActions() const { |
||||
|
// FIXME
|
||||
|
} |
||||
|
|
||||
|
void CompositionInformation::renameNonsilentActions(std::map<std::string, std::string> const& renaming) { |
||||
|
// FIXME
|
||||
|
} |
||||
|
|
||||
|
void CompositionInformation::setContainsRenameComposition() { |
||||
|
renameComposition = true; |
||||
|
} |
||||
|
|
||||
|
bool CompositionInformation::containsRenameComposition() const { |
||||
|
return renameComposition; |
||||
|
} |
||||
|
|
||||
|
void CompositionInformation::setContainsRestrictedParallelComposition() { |
||||
|
restrictedParallelComposition = true; |
||||
|
} |
||||
|
|
||||
|
bool CompositionInformation::containsRestrictedParallelComposition() const { |
||||
|
return restrictedParallelComposition; |
||||
|
} |
||||
|
|
||||
|
std::map<std::string, uint64_t> CompositionInformation::joinMultiplicityMaps(std::map<std::string, uint64_t> const& first, std::map<std::string, uint64_t> const& second) { |
||||
|
std::map<std::string, uint64_t> result = first; |
||||
|
for (auto const& element : second) { |
||||
|
result[element.first] += element.second; |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
std::map<std::string, uint64_t> const& CompositionInformation::getAutomatonToMultiplicityMap() const { |
||||
|
return automatonNameToMultiplicity; |
||||
|
} |
||||
|
|
||||
|
CompositionInformation CompositionInformationVisitor::getInformation(Composition const& composition, Model const& model) { |
||||
|
return boost::any_cast<CompositionInformation>(composition.accept(*this, model)); |
||||
|
} |
||||
|
|
||||
|
boost::any CompositionInformationVisitor::visit(AutomatonComposition const& composition, boost::any const& data) { |
||||
|
CompositionInformation result; |
||||
|
result.increaseAutomatonMultiplicity(composition.getAutomatonName()); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
boost::any CompositionInformationVisitor::visit(RenameComposition const& composition, boost::any const& data) { |
||||
|
CompositionInformation subresult = boost::any_cast<CompositionInformation>(composition.getSubcomposition().accept(*this, data)); |
||||
|
subresult.setContainsRenameComposition(); |
||||
|
return subresult; |
||||
|
} |
||||
|
|
||||
|
boost::any CompositionInformationVisitor::visit(ParallelComposition const& composition, boost::any const& data) { |
||||
|
Model const& model = boost::any_cast<Model const&>(data); |
||||
|
CompositionInformation left = boost::any_cast<CompositionInformation>(composition.getLeftSubcomposition().accept(*this, data)); |
||||
|
CompositionInformation right = boost::any_cast<CompositionInformation>(composition.getRightSubcomposition().accept(*this, data)); |
||||
|
|
||||
|
// Join the information from both sides.
|
||||
|
bool containsRenameComposition = left.containsRenameComposition() || right.containsRenameComposition(); |
||||
|
bool containsRestrictedParallelComposition = left.containsRestrictedParallelComposition() || right.containsRestrictedParallelComposition(); |
||||
|
std::map<std::string, uint64_t> joinedAutomatonToMultiplicity = CompositionInformation::joinMultiplicityMaps(left.getAutomatonToMultiplicityMap(), right.getAutomatonToMultiplicityMap()); |
||||
|
|
||||
|
// If there was no restricted parallel composition yet, maybe the current composition is one, so check it.
|
||||
|
if (!containsRestrictedParallelComposition) { |
||||
|
// FIXME.
|
||||
|
} |
||||
|
|
||||
|
return CompositionInformation(joinedAutomatonToMultiplicity, containsRenameComposition, containsRestrictedParallelComposition); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,60 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <map> |
||||
|
#include <set> |
||||
|
#include <cstdint> |
||||
|
|
||||
|
#include "src/storage/jani/CompositionVisitor.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace jani { |
||||
|
|
||||
|
class Model; |
||||
|
|
||||
|
class CompositionInformation { |
||||
|
public: |
||||
|
CompositionInformation() = default; |
||||
|
CompositionInformation(std::map<std::string, uint64_t> const& automatonNameToMultiplicity, std::set<std::string> const& nonsilentActions, bool containsRenaming, bool containsRestrictedParallelComposition); |
||||
|
|
||||
|
void increaseAutomatonMultiplicity(std::string const& automatonName, uint64_t count = 1); |
||||
|
|
||||
|
void addNonsilentAction(std::string const& actionName); |
||||
|
std::set<std::string> const& getNonsilentActions() const; |
||||
|
void renameNonsilentActions(std::map<std::string, std::string> const& renaming); |
||||
|
|
||||
|
void setContainsRenameComposition(); |
||||
|
bool containsRenameComposition() const; |
||||
|
|
||||
|
void setContainsRestrictedParallelComposition(); |
||||
|
bool containsRestrictedParallelComposition() const; |
||||
|
|
||||
|
static std::map<std::string, uint64_t> joinMultiplicityMaps(std::map<std::string, uint64_t> const& first, std::map<std::string, uint64_t> const& second); |
||||
|
std::map<std::string, uint64_t> const& getAutomatonToMultiplicityMap() const; |
||||
|
|
||||
|
private: |
||||
|
/// A mapping from the automata's names to the amount of times they occur in the composition. |
||||
|
std::map<std::string, uint64_t> automatonNameToMultiplicity; |
||||
|
|
||||
|
/// The set of non-silent actions contained in the composition. |
||||
|
std::set<std::string> nonsilentActions; |
||||
|
|
||||
|
/// A flag indicating whether the composition contains a renaming composition. |
||||
|
bool renameComposition; |
||||
|
|
||||
|
/// A flag indicating whether the composition contains |
||||
|
bool restrictedParallelComposition; |
||||
|
}; |
||||
|
|
||||
|
class CompositionInformationVisitor : public CompositionVisitor { |
||||
|
public: |
||||
|
CompositionInformationVisitor() = default; |
||||
|
|
||||
|
CompositionInformation getInformation(Composition const& composition, Model const& model); |
||||
|
|
||||
|
virtual boost::any visit(AutomatonComposition const& composition, boost::any const& data) override; |
||||
|
virtual boost::any visit(RenameComposition const& composition, boost::any const& data) override; |
||||
|
virtual boost::any visit(ParallelComposition const& composition, boost::any const& data) override; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
#include "src/storage/jani/AutomatonComposition.h" |
||||
|
#include "src/storage/jani/RenameComposition.h" |
||||
|
#include "src/storage/jani/ParallelComposition.h" |
Write
Preview
Loading…
Cancel
Save
Reference in new issue