You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
21 KiB

  1. #ifndef STORM_ADAPTERS_EXPLICITPRISMMODELBUILDER_H
  2. #define STORM_ADAPTERS_EXPLICITPRISMMODELBUILDER_H
  3. #include <memory>
  4. #include <utility>
  5. #include <vector>
  6. #include <queue>
  7. #include <cstdint>
  8. #include <boost/functional/hash.hpp>
  9. #include <boost/container/flat_set.hpp>
  10. #include <boost/container/flat_map.hpp>
  11. #include <src/models/sparse/StandardRewardModel.h>
  12. #include "src/storage/prism/Program.h"
  13. #include "src/storage/expressions/SimpleValuation.h"
  14. #include "src/storage/expressions/ExpressionEvaluator.h"
  15. #include "src/storage/BitVectorHashMap.h"
  16. #include "src/logic/Formulas.h"
  17. #include "src/models/sparse/StateAnnotation.h"
  18. #include "src/models/sparse/Model.h"
  19. #include "src/models/sparse/StateLabeling.h"
  20. #include "src/storage/SparseMatrix.h"
  21. #include "src/settings/SettingsManager.h"
  22. #include "src/utility/constants.h"
  23. #include "src/utility/prism.h"
  24. namespace storm {
  25. namespace utility {
  26. template<typename ValueType> class ConstantsComparator;
  27. }
  28. namespace builder {
  29. using namespace storm::utility::prism;
  30. // Forward-declare classes.
  31. template <typename ValueType> struct RewardModelBuilder;
  32. template<typename ValueType, typename RewardModelType = storm::models::sparse::StandardRewardModel<ValueType>, typename IndexType = uint32_t>
  33. class ExplicitPrismModelBuilder {
  34. public:
  35. typedef storm::storage::BitVector CompressedState;
  36. // A structure holding information about the reachable state space while building it.
  37. struct InternalStateInformation {
  38. InternalStateInformation(uint64_t bitsPerState);
  39. // This member stores all the states and maps them to their unique indices.
  40. storm::storage::BitVectorHashMap<IndexType> stateStorage;
  41. // A list of initial states in terms of their global indices.
  42. std::vector<IndexType> initialStateIndices;
  43. // The number of bits of each state.
  44. uint64_t bitsPerState;
  45. // A list of reachable states as indices in the stateToIndexMap.
  46. std::vector<storm::storage::BitVector> reachableStates;
  47. };
  48. // A structure holding information about the reachable state space that can be retrieved from the outside.
  49. struct StateInformation : public storm::models::sparse::StateAnnotation {
  50. /*!
  51. * Constructs a state information object for the given number of states.
  52. */
  53. StateInformation(uint_fast64_t numberOfStates);
  54. // A mapping from state indices to their variable valuations.
  55. std::vector<storm::expressions::SimpleValuation> valuations;
  56. std::string stateInfo(uint_fast64_t state) const override {
  57. return valuations[state].toString();
  58. }
  59. };
  60. // A structure storing information about the used variables of the program.
  61. struct VariableInformation {
  62. VariableInformation(storm::expressions::ExpressionManager const& manager);
  63. struct BooleanVariableInformation {
  64. BooleanVariableInformation(storm::expressions::Variable const& variable, bool initialValue, uint_fast64_t bitOffset);
  65. // The boolean variable.
  66. storm::expressions::Variable variable;
  67. // Its initial value.
  68. bool initialValue;
  69. // Its bit offset in the compressed state.
  70. uint_fast64_t bitOffset;
  71. };
  72. struct IntegerVariableInformation {
  73. 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);
  74. // The integer variable.
  75. storm::expressions::Variable variable;
  76. // Its initial value.
  77. int_fast64_t initialValue;
  78. // The lower bound of its range.
  79. int_fast64_t lowerBound;
  80. // The upper bound of its range.
  81. int_fast64_t upperBound;
  82. // Its bit offset in the compressed state.
  83. uint_fast64_t bitOffset;
  84. // Its bit width in the compressed state.
  85. uint_fast64_t bitWidth;
  86. };
  87. // Provide methods to access the bit offset and width of variables in the compressed state.
  88. uint_fast64_t getBitOffset(storm::expressions::Variable const& variable) const;
  89. uint_fast64_t getBitWidth(storm::expressions::Variable const& variable) const;
  90. // The known boolean variables.
  91. boost::container::flat_map<storm::expressions::Variable, uint_fast64_t> booleanVariableToIndexMap;
  92. std::vector<BooleanVariableInformation> booleanVariables;
  93. // The known integer variables.
  94. boost::container::flat_map<storm::expressions::Variable, uint_fast64_t> integerVariableToIndexMap;
  95. std::vector<IntegerVariableInformation> integerVariables;
  96. storm::expressions::ExpressionManager const& manager;
  97. };
  98. // A structure holding the individual components of a model.
  99. struct ModelComponents {
  100. ModelComponents();
  101. // The transition matrix.
  102. storm::storage::SparseMatrix<ValueType> transitionMatrix;
  103. // The state labeling.
  104. storm::models::sparse::StateLabeling stateLabeling;
  105. // The reward models associated with the model.
  106. std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<typename RewardModelType::ValueType>> rewardModels;
  107. // A vector that stores a labeling for each choice.
  108. boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>> choiceLabeling;
  109. };
  110. struct Options {
  111. /*!
  112. * Creates an object representing the default building options.
  113. */
  114. Options();
  115. /*! Creates an object representing the suggested building options assuming that the given formula is the
  116. * only one to check. Additional formulas may be preserved by calling <code>preserveFormula</code>.
  117. *
  118. * @param formula The formula based on which to choose the building options.
  119. */
  120. Options(storm::logic::Formula const& formula);
  121. /*! Creates an object representing the suggested building options assuming that the given formulas are
  122. * the only ones to check. Additional formulas may be preserved by calling <code>preserveFormula</code>.
  123. *
  124. * @param formula Thes formula based on which to choose the building options.
  125. */
  126. Options(std::vector<std::shared_ptr<storm::logic::Formula>> const& formulas);
  127. /*!
  128. * Sets the constants definitions from the given string. The string must be of the form 'X=a,Y=b,Z=c',
  129. * etc. where X,Y,Z are the variable names and a,b,c are the values of the constants.
  130. *
  131. * @param program The program managing the constants that shall be defined. Note that the program itself
  132. * is not modified whatsoever.
  133. * @param constantDefinitionString The string from which to parse the constants' values.
  134. */
  135. void addConstantDefinitionsFromString(storm::prism::Program const& program, std::string const& constantDefinitionString);
  136. /*!
  137. * Changes the options in a way that ensures that the given formula can be checked on the model once it
  138. * has been built.
  139. *
  140. * @param formula The formula that is to be ''preserved''.
  141. */
  142. void preserveFormula(storm::logic::Formula const& formula);
  143. /*!
  144. * Analyzes the given formula and sets an expression for the states states of the model that can be
  145. * treated as terminal states. Note that this may interfere with checking properties different than the
  146. * one provided.
  147. *
  148. * @param formula The formula used to (possibly) derive an expression for the terminal states of the
  149. * model.
  150. */
  151. void setTerminalStatesFromFormula(storm::logic::Formula const& formula);
  152. // A flag that indicates whether or not command labels are to be built.
  153. bool buildCommandLabels;
  154. // A flag that indicates whether or not all reward models are to be build.
  155. bool buildAllRewardModels;
  156. // A flag that indicates whether or not to store the state information after successfully building the
  157. // model. If it is to be preserved, it can be retrieved via the appropriate methods after a successful
  158. // call to <code>translateProgram</code>.
  159. bool buildStateInformation;
  160. // A list of reward models to be build in case not all reward models are to be build.
  161. std::set<std::string> rewardModelsToBuild;
  162. // An optional mapping that, if given, contains defining expressions for undefined constants.
  163. boost::optional<std::map<storm::expressions::Variable, storm::expressions::Expression>> constantDefinitions;
  164. // A flag that indicates whether all labels are to be build.
  165. bool buildAllLabels;
  166. // An optional set of labels that, if given, restricts the labels that are built.
  167. boost::optional<std::set<std::string>> labelsToBuild;
  168. // An optional set of expressions for which labels need to be built.
  169. boost::optional<std::vector<storm::expressions::Expression>> expressionLabels;
  170. // An optional expression or label that characterizes (a subset of) the terminal states of the model. If
  171. // this is set, the outgoing transitions of these states are replaced with a self-loop.
  172. boost::optional<boost::variant<storm::expressions::Expression, std::string>> terminalStates;
  173. // An optional expression or label whose negation characterizes (a subset of) the terminal states of the
  174. // model. If this is set, the outgoing transitions of these states are replaced with a self-loop.
  175. boost::optional<boost::variant<storm::expressions::Expression, std::string>> negatedTerminalStates;
  176. };
  177. /*!
  178. * Convert the program given at construction time to an abstract model. The type of the model is the one
  179. * specified in the program. The given reward model name selects the rewards that the model will contain.
  180. *
  181. * @param program The program to translate.
  182. * @param constantDefinitionString A string that contains a comma-separated definition of all undefined
  183. * constants in the model.
  184. * @param rewardModel The reward model that is to be built.
  185. * @return The explicit model that was given by the probabilistic program.
  186. */
  187. std::shared_ptr<storm::models::sparse::Model<ValueType, RewardModelType>> translateProgram(storm::prism::Program program, Options const& options = Options());
  188. /*!
  189. * If requested in the options, information about the variable valuations in the reachable states can be
  190. * retrieved via this function.
  191. *
  192. * @return A structure that stores information about all reachable states.
  193. */
  194. StateInformation const& getStateInformation() const;
  195. private:
  196. static void unpackStateIntoEvaluator(storm::storage::BitVector const& currentState, VariableInformation const& variableInformation, storm::expressions::ExpressionEvaluator<ValueType>& evaluator);
  197. static storm::expressions::SimpleValuation unpackStateIntoValuation(storm::storage::BitVector const& currentState, VariableInformation const& variableInformation);
  198. /*!
  199. * Applies an update to the given state and returns the resulting new state object. This methods does not
  200. * modify the given state but returns a new one.
  201. *
  202. * @params state The state to which to apply the update.
  203. * @params update The update to apply.
  204. * @return The resulting state.
  205. */
  206. static CompressedState applyUpdate(VariableInformation const& variableInformation, CompressedState const& state, storm::prism::Update const& update, storm::expressions::ExpressionEvaluator<ValueType> const& evaluator);
  207. /*!
  208. * Applies an update to the given state and returns the resulting new state object. The update is evaluated
  209. * over the variable values of the given base state. This methods does not modify the given state but
  210. * returns a new one.
  211. *
  212. * @param state The state to which to apply the update.
  213. * @param baseState The state used for evaluating the update.
  214. * @param update The update to apply.
  215. * @return The resulting state.
  216. */
  217. static CompressedState applyUpdate(VariableInformation const& variableInformation, CompressedState const& state, CompressedState const& baseState, storm::prism::Update const& update, storm::expressions::ExpressionEvaluator<ValueType> const& evaluator);
  218. /*!
  219. * Retrieves the state id of the given state. If the state has not been encountered yet, it will be added to
  220. * the lists of all states with a new id. If the state was already known, the object that is pointed to by
  221. * the given state pointer is deleted and the old state id is returned. Note that the pointer should not be
  222. * used after invoking this method.
  223. *
  224. * @param state A pointer to a state for which to retrieve the index. This must not be used after the call.
  225. * @param internalStateInformation The information about the already explored part of the reachable state space.
  226. * @return A pair indicating whether the state was already discovered before and the state id of the state.
  227. */
  228. static IndexType getOrAddStateIndex(CompressedState const& state, InternalStateInformation& internalStateInformation, std::queue<storm::storage::BitVector>& stateQueue);
  229. /*!
  230. * Retrieves all commands that are labeled with the given label and enabled in the given state, grouped by
  231. * modules.
  232. *
  233. * This function will iterate over all modules and retrieve all commands that are labeled with the given
  234. * action and active (i.e. enabled) in the current state. The result is a list of lists of commands in which
  235. * the inner lists contain all commands of exactly one module. If a module does not have *any* (including
  236. * disabled) commands, there will not be a list of commands of that module in the result. If, however, the
  237. * module has a command with a relevant label, but no enabled one, nothing is returned to indicate that there
  238. * is no legal transition possible.
  239. *
  240. * @param The program in which to search for active commands.
  241. * @param state The current state.
  242. * @param actionIndex The index of the action label to select.
  243. * @return A list of lists of active commands or nothing.
  244. */
  245. static boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> getActiveCommandsByActionIndex(storm::prism::Program const& program,storm::expressions::ExpressionEvaluator<ValueType> const& evaluator, uint_fast64_t const& actionIndex);
  246. static std::vector<Choice<ValueType>> getUnlabeledTransitions(storm::prism::Program const& program, bool discreteTimeModel, InternalStateInformation& internalStateInformation, VariableInformation const& variableInformation, storm::storage::BitVector const& currentState, bool choiceLabeling, storm::expressions::ExpressionEvaluator<ValueType> const& evaluator, std::queue<storm::storage::BitVector>& stateQueue, storm::utility::ConstantsComparator<ValueType> const& comparator);
  247. static std::vector<Choice<ValueType>> getLabeledTransitions(storm::prism::Program const& program, bool discreteTimeModel, InternalStateInformation& internalStateInformation, VariableInformation const& variableInformation, storm::storage::BitVector const& currentState, bool choiceLabeling, storm::expressions::ExpressionEvaluator<ValueType> const& evaluator, std::queue<storm::storage::BitVector>& stateQueue, storm::utility::ConstantsComparator<ValueType> const& comparator);
  248. /*!
  249. * Builds the transition matrix and the transition reward matrix based for the given program.
  250. *
  251. * @param program The program for which to build the matrices.
  252. * @param variableInformation A structure containing information about the variables in the program.
  253. * @param transitionRewards A list of transition rewards that are to be considered in the transition reward
  254. * matrix.
  255. * @param internalStateInformation A structure containing information about the states of the program.
  256. * @param deterministicModel A flag indicating whether the model is supposed to be deterministic or not.
  257. * @param transitionMatrix A reference to an initialized matrix which is filled with all transitions by this
  258. * function.
  259. * @param rewardModelBuilders A vector of reward model builders that is used to build the vector of selected
  260. * reward models.
  261. * @param terminalExpression If given, terminal states are not explored further.
  262. * @return A tuple containing a vector with all rows at which the nondeterministic choices of each state begin
  263. * and a vector containing the labels associated with each choice.
  264. */
  265. static boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>> buildMatrices(storm::prism::Program const& program, VariableInformation const& variableInformation, std::vector<std::reference_wrapper<storm::prism::RewardModel const>> const& selectedRewardModels, InternalStateInformation& internalStateInformation, bool commandLabels, bool deterministicModel, bool discreteTimeModel, storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, std::vector<RewardModelBuilder<typename RewardModelType::ValueType>>& rewardModelBuilders, boost::optional<storm::expressions::Expression> const& terminalExpression);
  266. /*!
  267. * Explores the state space of the given program and returns the components of the model as a result.
  268. *
  269. * @param program The program whose state space to explore.
  270. * @param selectedRewardModels The reward models that are to be considered.
  271. * @param options A set of options used to customize the building process.
  272. * @return A structure containing the components of the resulting model.
  273. */
  274. ModelComponents buildModelComponents(storm::prism::Program const& program, std::vector<std::reference_wrapper<storm::prism::RewardModel const>> const& selectedRewardModels, Options const& options);
  275. /*!
  276. * Builds the state labeling for the given program.
  277. *
  278. * @param program The program for which to build the state labeling.
  279. * @param variableInformation Information about the variables in the program.
  280. * @param internalStateInformation Information about the state space of the program.
  281. * @return The state labeling of the given program.
  282. */
  283. static storm::models::sparse::StateLabeling buildStateLabeling(storm::prism::Program const& program, VariableInformation const& variableInformation, InternalStateInformation const& internalStateInformation);
  284. // This member holds information about reachable states that can be retrieved from the outside after a
  285. // successful build.
  286. boost::optional<StateInformation> stateInformation;
  287. };
  288. } // namespace adapters
  289. } // namespace storm
  290. #endif /* STORM_ADAPTERS_EXPLICITPRISMMODELBUILDER_H */