51 changed files with 2107 additions and 1188 deletions
-
2src/CMakeLists.txt
-
898src/builder/ExplicitPrismModelBuilder.cpp
-
181src/builder/ExplicitPrismModelBuilder.h
-
22src/builder/ExplorationOrder.cpp
-
17src/builder/ExplorationOrder.h
-
105src/generator/Choice.cpp
-
150src/generator/Choice.h
-
23src/generator/CompressedState.cpp
-
30src/generator/CompressedState.h
-
24src/generator/NextStateGenerator.h
-
404src/generator/PrismNextStateGenerator.cpp
-
108src/generator/PrismNextStateGenerator.h
-
50src/generator/PrismStateLabelingGenerator.cpp
-
31src/generator/PrismStateLabelingGenerator.h
-
57src/generator/StateBehavior.cpp
-
73src/generator/StateBehavior.h
-
20src/generator/StateLabelingGenerator.h
-
77src/generator/VariableInformation.cpp
-
75src/generator/VariableInformation.h
-
2src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp
-
4src/parser/PrismParser.cpp
-
16src/settings/ArgumentValidators.h
-
21src/settings/modules/GeneralSettings.cpp
-
19src/settings/modules/GeneralSettings.h
-
250src/storage/BitVector.cpp
-
9src/storage/BitVector.h
-
9src/storage/BitVectorHashMap.cpp
-
9src/storage/BitVectorHashMap.h
-
62src/storage/Distribution.cpp
-
36src/storage/Distribution.h
-
279src/storage/SparseMatrix.cpp
-
61src/storage/SparseMatrix.h
-
6src/storage/dd/Add.cpp
-
8src/storage/prism/Program.cpp
-
12src/storage/prism/Program.h
-
2src/storage/prism/RewardModel.cpp
-
4src/utility/constants.cpp
-
4src/utility/storm.h
-
32test/functional/builder/ExplicitPrismModelBuilderTest.cpp
-
8test/functional/modelchecker/GmmxxCtmcCslModelCheckerTest.cpp
-
2test/functional/modelchecker/GmmxxDtmcPrctlModelCheckerTest.cpp
-
2test/functional/modelchecker/GmmxxMdpPrctlModelCheckerTest.cpp
-
8test/functional/modelchecker/NativeCtmcCslModelCheckerTest.cpp
-
2test/functional/permissiveschedulers/MilpPermissiveSchedulerTest.cpp
-
2test/functional/permissiveschedulers/SmtPermissiveSchedulerTest.cpp
-
18test/functional/storage/BitVectorHashMapTest.cpp
-
18test/functional/storage/BitVectorTest.cpp
-
2test/functional/storage/NondeterministicModelBisimulationDecompositionTest.cpp
-
4test/functional/storage/SparseMatrixTest.cpp
-
8test/functional/utility/GraphTest.cpp
-
29test/functional/utility/ModelInstantiatorTest.cpp
898
src/builder/ExplicitPrismModelBuilder.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,22 @@ |
|||
#include "src/builder/ExplorationOrder.h"
|
|||
|
|||
namespace storm { |
|||
namespace builder { |
|||
|
|||
std::ostream& operator<<(std::ostream& out, ExplorationOrder const& order) { |
|||
switch (order) { |
|||
case ExplorationOrder::Dfs: |
|||
out << "depth-first"; |
|||
break; |
|||
case ExplorationOrder::Bfs: |
|||
out << "breadth-first"; |
|||
break; |
|||
default: |
|||
out << "undefined"; |
|||
break; |
|||
} |
|||
return out; |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,17 @@ |
|||
#ifndef STORM_BUILDER_EXPLORATIONORDER_H_ |
|||
#define STORM_BUILDER_EXPLORATIONORDER_H_ |
|||
|
|||
#include <ostream> |
|||
|
|||
namespace storm { |
|||
namespace builder { |
|||
|
|||
// An enum that contains all currently supported exploration orders. |
|||
enum class ExplorationOrder { Dfs, Bfs }; |
|||
|
|||
std::ostream& operator<<(std::ostream& out, ExplorationOrder const& order); |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_BUILDER_EXPLORATIONORDER_H_ */ |
@ -0,0 +1,105 @@ |
|||
#include "src/generator/Choice.h"
|
|||
|
|||
#include "src/adapters/CarlAdapter.h"
|
|||
|
|||
#include "src/utility/constants.h"
|
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
Choice<ValueType, StateType>::Choice(uint_fast64_t actionIndex, bool markovian) : markovian(markovian), actionIndex(actionIndex), distribution(), totalMass(storm::utility::zero<ValueType>()), choiceRewards() { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
typename storm::storage::Distribution<ValueType, StateType>::iterator Choice<ValueType, StateType>::begin() { |
|||
return distribution.begin(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
typename storm::storage::Distribution<ValueType, StateType>::const_iterator Choice<ValueType, StateType>::begin() const { |
|||
return distribution.cbegin(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
typename storm::storage::Distribution<ValueType, StateType>::iterator Choice<ValueType, StateType>::end() { |
|||
return distribution.end(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
typename storm::storage::Distribution<ValueType, StateType>::const_iterator Choice<ValueType, StateType>::end() const { |
|||
return distribution.cend(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void Choice<ValueType, StateType>::addChoiceLabel(uint_fast64_t label) { |
|||
if (!choiceLabels) { |
|||
choiceLabels = LabelSet(); |
|||
} |
|||
choiceLabels->insert(label); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void Choice<ValueType, StateType>::addChoiceLabels(LabelSet const& labelSet) { |
|||
if (!choiceLabels) { |
|||
choiceLabels = LabelSet(); |
|||
} |
|||
choiceLabels->insert(labelSet.begin(), labelSet.end()); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
boost::container::flat_set<uint_fast64_t> const& Choice<ValueType, StateType>::getChoiceLabels() const { |
|||
return *choiceLabels; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
uint_fast64_t Choice<ValueType, StateType>::getActionIndex() const { |
|||
return actionIndex; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
ValueType Choice<ValueType, StateType>::getTotalMass() const { |
|||
return totalMass; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void Choice<ValueType, StateType>::addProbability(StateType const& state, ValueType const& value) { |
|||
totalMass += value; |
|||
distribution.addProbability(state, value); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void Choice<ValueType, StateType>::addChoiceReward(ValueType const& value) { |
|||
choiceRewards.push_back(value); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::vector<ValueType> const& Choice<ValueType, StateType>::getChoiceRewards() const { |
|||
return choiceRewards; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
bool Choice<ValueType, StateType>::isMarkovian() const { |
|||
return markovian; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::size_t Choice<ValueType, StateType>::size() const { |
|||
return distribution.size(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::ostream& operator<<(std::ostream& out, Choice<ValueType, StateType> const& choice) { |
|||
out << "<"; |
|||
for (auto const& stateProbabilityPair : choice) { |
|||
out << stateProbabilityPair.first << " : " << stateProbabilityPair.second << ", "; |
|||
} |
|||
out << ">"; |
|||
return out; |
|||
} |
|||
|
|||
template class Choice<double>; |
|||
template class Choice<storm::RationalFunction>; |
|||
} |
|||
} |
@ -0,0 +1,150 @@ |
|||
#ifndef STORM_GENERATOR_CHOICE_H_ |
|||
#define STORM_GENERATOR_CHOICE_H_ |
|||
|
|||
#include <cstdint> |
|||
#include <functional> |
|||
|
|||
#include <boost/optional.hpp> |
|||
#include <boost/container/flat_set.hpp> |
|||
|
|||
#include "src/storage/Distribution.h" |
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
// A structure holding information about a particular choice. |
|||
template<typename ValueType, typename StateType=uint32_t> |
|||
struct Choice { |
|||
public: |
|||
typedef boost::container::flat_set<uint_fast64_t> LabelSet; |
|||
|
|||
Choice(uint_fast64_t actionIndex = 0, bool markovian = false); |
|||
|
|||
Choice(Choice const& other) = default; |
|||
Choice& operator=(Choice const& other) = default; |
|||
Choice(Choice&& other) = default; |
|||
Choice& operator=(Choice&& other) = default; |
|||
|
|||
/*! |
|||
* Returns an iterator to the distribution associated with this choice. |
|||
* |
|||
* @return An iterator to the first element of the distribution. |
|||
*/ |
|||
typename storm::storage::Distribution<ValueType, StateType>::iterator begin(); |
|||
|
|||
/*! |
|||
* Returns an iterator to the distribution associated with this choice. |
|||
* |
|||
* @return An iterator to the first element of the distribution. |
|||
*/ |
|||
typename storm::storage::Distribution<ValueType, StateType>::const_iterator begin() const; |
|||
|
|||
/*! |
|||
* Returns an iterator past the end of the distribution associated with this choice. |
|||
* |
|||
* @return An iterator past the end of the distribution. |
|||
*/ |
|||
typename storm::storage::Distribution<ValueType, StateType>::iterator end(); |
|||
|
|||
/*! |
|||
* Returns an iterator past the end of the distribution associated with this choice. |
|||
* |
|||
* @return An iterator past the end of the distribution. |
|||
*/ |
|||
typename storm::storage::Distribution<ValueType, StateType>::const_iterator end() const; |
|||
|
|||
/*! |
|||
* Inserts the contents of this object to the given output stream. |
|||
* |
|||
* @param out The stream in which to insert the contents. |
|||
*/ |
|||
template<typename ValueTypePrime, typename StateTypePrime> |
|||
friend std::ostream& operator<<(std::ostream& out, Choice<ValueTypePrime, StateTypePrime> const& choice); |
|||
|
|||
/*! |
|||
* Adds the given label to the labels associated with this choice. |
|||
* |
|||
* @param label The label to associate with this choice. |
|||
*/ |
|||
void addChoiceLabel(uint_fast64_t label); |
|||
|
|||
/*! |
|||
* Adds the given label set to the labels associated with this choice. |
|||
* |
|||
* @param labelSet The label set to associate with this choice. |
|||
*/ |
|||
void addChoiceLabels(LabelSet const& labelSet); |
|||
|
|||
/*! |
|||
* Retrieves the set of labels associated with this choice. |
|||
* |
|||
* @return The set of labels associated with this choice. |
|||
*/ |
|||
LabelSet const& getChoiceLabels() const; |
|||
|
|||
/*! |
|||
* Retrieves the index of the action of this choice. |
|||
* |
|||
* @return The index of the action of this choice. |
|||
*/ |
|||
uint_fast64_t getActionIndex() const; |
|||
|
|||
/*! |
|||
* Retrieves the total mass of this choice. |
|||
* |
|||
* @return The total mass. |
|||
*/ |
|||
ValueType getTotalMass() const; |
|||
|
|||
/*! |
|||
* Adds the given probability value to the given state in the underlying distribution. |
|||
*/ |
|||
void addProbability(StateType const& state, ValueType const& value); |
|||
|
|||
/*! |
|||
* Adds the given value to the reward associated with this choice. |
|||
*/ |
|||
void addChoiceReward(ValueType const& value); |
|||
|
|||
/*! |
|||
* Retrieves the rewards for this choice under selected reward models. |
|||
*/ |
|||
std::vector<ValueType> const& getChoiceRewards() const; |
|||
|
|||
/*! |
|||
* Retrieves whether the choice is Markovian. |
|||
*/ |
|||
bool isMarkovian() const; |
|||
|
|||
/*! |
|||
* Retrieves the size of the distribution associated with this choice. |
|||
*/ |
|||
std::size_t size() const; |
|||
|
|||
private: |
|||
// A flag indicating whether this choice is Markovian or not. |
|||
bool markovian; |
|||
|
|||
// The action index associated with this choice. |
|||
uint_fast64_t actionIndex; |
|||
|
|||
// The distribution that is associated with the choice. |
|||
storm::storage::Distribution<ValueType, StateType> distribution; |
|||
|
|||
// The total probability mass (or rates) of this choice. |
|||
ValueType totalMass; |
|||
|
|||
// The reward values associated with this choice. |
|||
std::vector<ValueType> choiceRewards; |
|||
|
|||
// The labels that are associated with this choice. |
|||
boost::optional<LabelSet> choiceLabels; |
|||
}; |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::ostream& operator<<(std::ostream& out, Choice<ValueType, StateType> const& choice); |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_CHOICE_H_ */ |
@ -0,0 +1,23 @@ |
|||
#include "src/generator/CompressedState.h"
|
|||
|
|||
#include "src/generator/VariableInformation.h"
|
|||
#include "src/storage/expressions/ExpressionEvaluator.h"
|
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType> |
|||
void unpackStateIntoEvaluator(CompressedState const& state, VariableInformation const& variableInformation, storm::expressions::ExpressionEvaluator<ValueType>& evaluator) { |
|||
for (auto const& booleanVariable : variableInformation.booleanVariables) { |
|||
evaluator.setBooleanValue(booleanVariable.variable, state.get(booleanVariable.bitOffset)); |
|||
} |
|||
for (auto const& integerVariable : variableInformation.integerVariables) { |
|||
evaluator.setIntegerValue(integerVariable.variable, state.getAsInt(integerVariable.bitOffset, integerVariable.bitWidth) + integerVariable.lowerBound); |
|||
} |
|||
|
|||
} |
|||
|
|||
template void unpackStateIntoEvaluator<double>(CompressedState const& state, VariableInformation const& variableInformation, storm::expressions::ExpressionEvaluator<double>& evaluator); |
|||
template void unpackStateIntoEvaluator<storm::RationalFunction>(CompressedState const& state, VariableInformation const& variableInformation, storm::expressions::ExpressionEvaluator<storm::RationalFunction>& evaluator); |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
#ifndef STORM_GENERATOR_COMPRESSEDSTATE_H_ |
|||
#define STORM_GENERATOR_COMPRESSEDSTATE_H_ |
|||
|
|||
#include "src/storage/BitVector.h" |
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
template<typename ValueType> class ExpressionEvaluator; |
|||
} |
|||
|
|||
namespace generator { |
|||
|
|||
typedef storm::storage::BitVector CompressedState; |
|||
|
|||
class VariableInformation; |
|||
|
|||
/*! |
|||
* Unpacks the compressed state into the evaluator. |
|||
* |
|||
* @param state The state to unpack. |
|||
* @param variableInformation The information about how the variables are packed with the state. |
|||
* @param evaluator The evaluator into which to load the state. |
|||
*/ |
|||
template<typename ValueType> |
|||
void unpackStateIntoEvaluator(CompressedState const& state, VariableInformation const& variableInformation, storm::expressions::ExpressionEvaluator<ValueType>& evaluator); |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_COMPRESSEDSTATE_H_ */ |
|||
|
@ -0,0 +1,24 @@ |
|||
#ifndef STORM_GENERATOR_NEXTSTATEGENERATOR_H_ |
|||
#define STORM_GENERATOR_NEXTSTATEGENERATOR_H_ |
|||
|
|||
#include <vector> |
|||
#include <cstdint> |
|||
|
|||
#include "src/generator/CompressedState.h" |
|||
#include "src/generator/StateBehavior.h" |
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
template<typename ValueType, typename StateType = uint32_t> |
|||
class NextStateGenerator { |
|||
public: |
|||
typedef std::function<StateType (CompressedState const&)> StateToIdCallback; |
|||
|
|||
virtual bool isDeterministicModel() const = 0; |
|||
virtual std::vector<StateType> getInitialStates(StateToIdCallback const& stateToIdCallback) = 0; |
|||
virtual StateBehavior<ValueType, StateType> expand(CompressedState const& state, StateToIdCallback const& stateToIdCallback) = 0; |
|||
}; |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_NEXTSTATEGENERATOR_H_ */ |
@ -0,0 +1,404 @@ |
|||
#include "src/generator/PrismNextStateGenerator.h"
|
|||
|
|||
#include <boost/container/flat_map.hpp>
|
|||
|
|||
#include "src/utility/constants.h"
|
|||
#include "src/utility/macros.h"
|
|||
#include "src/exceptions/WrongFormatException.h"
|
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
PrismNextStateGenerator<ValueType, StateType>::PrismNextStateGenerator(storm::prism::Program const& program, VariableInformation const& variableInformation, bool buildChoiceLabeling) : program(program), selectedRewardModels(), buildChoiceLabeling(buildChoiceLabeling), variableInformation(variableInformation), evaluator(program.getManager()), comparator() { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void PrismNextStateGenerator<ValueType, StateType>::addRewardModel(storm::prism::RewardModel const& rewardModel) { |
|||
selectedRewardModels.push_back(rewardModel); |
|||
hasStateActionRewards |= rewardModel.hasStateActionRewards(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void PrismNextStateGenerator<ValueType, StateType>::setTerminalExpression(storm::expressions::Expression const& terminalExpression) { |
|||
this->terminalExpression = terminalExpression; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
bool PrismNextStateGenerator<ValueType, StateType>::isDeterministicModel() const { |
|||
return program.isDeterministicModel(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::vector<StateType> PrismNextStateGenerator<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> |
|||
StateBehavior<ValueType, StateType> PrismNextStateGenerator<ValueType, StateType>::expand(CompressedState const& state, StateToIdCallback const& stateToIdCallback) { |
|||
// Since almost all subsequent operations are based on the evaluator, we load the state into it now.
|
|||
unpackStateIntoEvaluator(state, variableInformation, evaluator); |
|||
|
|||
// Prepare the result, in case we return early.
|
|||
StateBehavior<ValueType, StateType> result; |
|||
|
|||
// First, construct the state rewards, as we may return early if there are no choices later and we already
|
|||
// need the state rewards then.
|
|||
for (auto const& rewardModel : selectedRewardModels) { |
|||
ValueType stateRewardValue = storm::utility::zero<ValueType>(); |
|||
if (rewardModel.get().hasStateRewards()) { |
|||
for (auto const& stateReward : rewardModel.get().getStateRewards()) { |
|||
if (evaluator.asBool(stateReward.getStatePredicateExpression())) { |
|||
stateRewardValue += ValueType(evaluator.asRational(stateReward.getRewardValueExpression())); |
|||
} |
|||
} |
|||
} |
|||
result.addStateReward(stateRewardValue); |
|||
} |
|||
|
|||
// If a terminal expression was set and we must not expand this state, return now.
|
|||
if (terminalExpression && evaluator.asBool(terminalExpression.get())) { |
|||
return result; |
|||
} |
|||
|
|||
// Get all choices for the state.
|
|||
std::vector<Choice<ValueType>> allChoices = getUnlabeledChoices(state, stateToIdCallback); |
|||
std::vector<Choice<ValueType>> allLabeledChoices = getLabeledChoices(state, stateToIdCallback); |
|||
for (auto& choice : allLabeledChoices) { |
|||
allChoices.push_back(std::move(choice)); |
|||
} |
|||
|
|||
std::size_t totalNumberOfChoices = allChoices.size(); |
|||
|
|||
// If there is not a single choice, we return immediately, because the state has no behavior (other than
|
|||
// the state reward).
|
|||
if (totalNumberOfChoices == 0) { |
|||
return result; |
|||
} |
|||
|
|||
// If the model is a deterministic model, we need to fuse the choices into one.
|
|||
if (program.isDeterministicModel() && totalNumberOfChoices > 1) { |
|||
Choice<ValueType> globalChoice; |
|||
|
|||
// For CTMCs, we need to keep track of the total exit rate to scale the action rewards later. For DTMCs
|
|||
// this is equal to the number of choices, which is why we initialize it like this here.
|
|||
ValueType totalExitRate = program.isDiscreteTimeModel() ? static_cast<ValueType>(totalNumberOfChoices) : storm::utility::zero<ValueType>(); |
|||
|
|||
// Iterate over all choices and combine the probabilities/rates into one choice.
|
|||
for (auto const& choice : allChoices) { |
|||
for (auto const& stateProbabilityPair : choice) { |
|||
if (program.isDiscreteTimeModel()) { |
|||
globalChoice.addProbability(stateProbabilityPair.first, stateProbabilityPair.second / totalNumberOfChoices); |
|||
} else { |
|||
globalChoice.addProbability(stateProbabilityPair.first, stateProbabilityPair.second); |
|||
} |
|||
} |
|||
|
|||
if (hasStateActionRewards && !program.isDiscreteTimeModel()) { |
|||
totalExitRate += choice.getTotalMass(); |
|||
} |
|||
|
|||
if (buildChoiceLabeling) { |
|||
globalChoice.addChoiceLabels(choice.getChoiceLabels()); |
|||
} |
|||
} |
|||
|
|||
// Now construct the state-action reward for all selected reward models.
|
|||
for (auto const& rewardModel : selectedRewardModels) { |
|||
ValueType stateActionRewardValue = storm::utility::zero<ValueType>(); |
|||
if (rewardModel.get().hasStateActionRewards()) { |
|||
for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) { |
|||
for (auto const& choice : allChoices) { |
|||
if (stateActionReward.getActionIndex() == choice.getActionIndex() && evaluator.asBool(stateActionReward.getStatePredicateExpression())) { |
|||
stateActionRewardValue += ValueType(evaluator.asRational(stateActionReward.getRewardValueExpression())) * choice.getTotalMass() / totalExitRate; |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
globalChoice.addChoiceReward(stateActionRewardValue); |
|||
} |
|||
|
|||
// Move the newly fused choice in place.
|
|||
allChoices.clear(); |
|||
allChoices.push_back(std::move(globalChoice)); |
|||
} |
|||
|
|||
// Move all remaining choices in place.
|
|||
for (auto& choice : allChoices) { |
|||
result.addChoice(std::move(choice)); |
|||
} |
|||
|
|||
result.setExpanded(); |
|||
return result; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
CompressedState PrismNextStateGenerator<ValueType, StateType>::applyUpdate(CompressedState const& state, storm::prism::Update const& update) { |
|||
CompressedState newState(state); |
|||
|
|||
auto assignmentIt = update.getAssignments().begin(); |
|||
auto assignmentIte = update.getAssignments().end(); |
|||
|
|||
// Iterate over all boolean assignments and carry them out.
|
|||
auto boolIt = variableInformation.booleanVariables.begin(); |
|||
for (; assignmentIt != assignmentIte && assignmentIt->getExpression().hasBooleanType(); ++assignmentIt) { |
|||
while (assignmentIt->getVariable() != boolIt->variable) { |
|||
++boolIt; |
|||
} |
|||
newState.set(boolIt->bitOffset, evaluator.asBool(assignmentIt->getExpression())); |
|||
} |
|||
|
|||
// Iterate over all integer assignments and carry them out.
|
|||
auto integerIt = variableInformation.integerVariables.begin(); |
|||
for (; assignmentIt != assignmentIte && assignmentIt->getExpression().hasIntegerType(); ++assignmentIt) { |
|||
while (assignmentIt->getVariable() != integerIt->variable) { |
|||
++integerIt; |
|||
} |
|||
int_fast64_t assignedValue = evaluator.asInt(assignmentIt->getExpression()); |
|||
STORM_LOG_THROW(assignedValue <= integerIt->upperBound, storm::exceptions::WrongFormatException, "The update " << update << " leads to an out-of-bounds value (" << assignedValue << ") for the variable '" << assignmentIt->getVariableName() << "'."); |
|||
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> |
|||
boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> PrismNextStateGenerator<ValueType, StateType>::getActiveCommandsByActionIndex(uint_fast64_t const& actionIndex) { |
|||
boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> result((std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>())); |
|||
|
|||
// Iterate over all modules.
|
|||
for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) { |
|||
storm::prism::Module const& module = program.getModule(i); |
|||
|
|||
// If the module has no command labeled with the given action, we can skip this module.
|
|||
if (!module.hasActionIndex(actionIndex)) { |
|||
continue; |
|||
} |
|||
|
|||
std::set<uint_fast64_t> const& commandIndices = module.getCommandIndicesByActionIndex(actionIndex); |
|||
|
|||
// If the module contains the action, but there is no command in the module that is labeled with
|
|||
// this action, we don't have any feasible command combinations.
|
|||
if (commandIndices.empty()) { |
|||
return boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>>(); |
|||
} |
|||
|
|||
std::vector<std::reference_wrapper<storm::prism::Command const>> commands; |
|||
|
|||
// Look up commands by their indices and add them if the guard evaluates to true in the given state.
|
|||
for (uint_fast64_t commandIndex : commandIndices) { |
|||
storm::prism::Command const& command = module.getCommand(commandIndex); |
|||
if (evaluator.asBool(command.getGuardExpression())) { |
|||
commands.push_back(command); |
|||
} |
|||
} |
|||
|
|||
// If there was no enabled command although the module has some command with the required action label,
|
|||
// we must not return anything.
|
|||
if (commands.size() == 0) { |
|||
return boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>>(); |
|||
} |
|||
|
|||
result.get().push_back(std::move(commands)); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::vector<Choice<ValueType>> PrismNextStateGenerator<ValueType, StateType>::getUnlabeledChoices(CompressedState const& state, StateToIdCallback stateToIdCallback) { |
|||
std::vector<Choice<ValueType>> result; |
|||
|
|||
// Iterate over all modules.
|
|||
for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) { |
|||
storm::prism::Module const& module = program.getModule(i); |
|||
|
|||
// Iterate over all commands.
|
|||
for (uint_fast64_t j = 0; j < module.getNumberOfCommands(); ++j) { |
|||
storm::prism::Command const& command = module.getCommand(j); |
|||
|
|||
// Only consider unlabeled commands.
|
|||
if (command.isLabeled()) continue; |
|||
|
|||
// Skip the command, if it is not enabled.
|
|||
if (!evaluator.asBool(command.getGuardExpression())) { |
|||
continue; |
|||
} |
|||
|
|||
result.push_back(Choice<ValueType>(command.getActionIndex())); |
|||
Choice<ValueType>& choice = result.back(); |
|||
|
|||
// Remember the command labels only if we were asked to.
|
|||
if (buildChoiceLabeling) { |
|||
choice.addChoiceLabel(command.getGlobalIndex()); |
|||
} |
|||
|
|||
// Iterate over all updates of the current command.
|
|||
ValueType probabilitySum = storm::utility::zero<ValueType>(); |
|||
for (uint_fast64_t k = 0; k < command.getNumberOfUpdates(); ++k) { |
|||
storm::prism::Update const& update = command.getUpdate(k); |
|||
|
|||
// Obtain target state index and add it to the list of known states. If it has not yet been
|
|||
// seen, we also add it to the set of states that have yet to be explored.
|
|||
StateType stateIndex = stateToIdCallback(applyUpdate(state, update)); |
|||
|
|||
// Update the choice by adding the probability/target state to it.
|
|||
ValueType probability = evaluator.asRational(update.getLikelihoodExpression()); |
|||
choice.addProbability(stateIndex, probability); |
|||
probabilitySum += probability; |
|||
} |
|||
|
|||
// Create the state-action reward for the newly created choice.
|
|||
for (auto const& rewardModel : selectedRewardModels) { |
|||
ValueType stateActionRewardValue = storm::utility::zero<ValueType>(); |
|||
if (rewardModel.get().hasStateActionRewards()) { |
|||
for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) { |
|||
if (stateActionReward.getActionIndex() == choice.getActionIndex() && evaluator.asBool(stateActionReward.getStatePredicateExpression())) { |
|||
stateActionRewardValue += ValueType(evaluator.asRational(stateActionReward.getRewardValueExpression())) * choice.getTotalMass(); |
|||
} |
|||
} |
|||
} |
|||
choice.addChoiceReward(stateActionRewardValue); |
|||
} |
|||
|
|||
// Check that the resulting distribution is in fact a distribution.
|
|||
STORM_LOG_THROW(!program.isDiscreteTimeModel() || comparator.isOne(probabilitySum), storm::exceptions::WrongFormatException, "Probabilities do not sum to one for command '" << command << "' (actually sum to " << probabilitySum << ")."); |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::vector<Choice<ValueType>> PrismNextStateGenerator<ValueType, StateType>::getLabeledChoices(CompressedState const& state, StateToIdCallback stateToIdCallback) { |
|||
std::vector<Choice<ValueType>> result; |
|||
|
|||
for (uint_fast64_t actionIndex : program.getSynchronizingActionIndices()) { |
|||
boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> optionalActiveCommandLists = getActiveCommandsByActionIndex(actionIndex); |
|||
|
|||
// Only process this action label, if there is at least one feasible solution.
|
|||
if (optionalActiveCommandLists) { |
|||
std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>> const& activeCommandList = optionalActiveCommandLists.get(); |
|||
std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>::const_iterator> iteratorList(activeCommandList.size()); |
|||
|
|||
// Initialize the list of iterators.
|
|||
for (size_t i = 0; i < activeCommandList.size(); ++i) { |
|||
iteratorList[i] = activeCommandList[i].cbegin(); |
|||
} |
|||
|
|||
// As long as there is one feasible combination of commands, keep on expanding it.
|
|||
bool done = false; |
|||
while (!done) { |
|||
boost::container::flat_map<CompressedState, ValueType>* currentTargetStates = new boost::container::flat_map<CompressedState, ValueType>(); |
|||
boost::container::flat_map<CompressedState, ValueType>* newTargetStates = new boost::container::flat_map<CompressedState, ValueType>(); |
|||
|
|||
currentTargetStates->emplace(state, storm::utility::one<ValueType>()); |
|||
|
|||
for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) { |
|||
storm::prism::Command const& command = *iteratorList[i]; |
|||
|
|||
for (uint_fast64_t j = 0; j < command.getNumberOfUpdates(); ++j) { |
|||
storm::prism::Update const& update = command.getUpdate(j); |
|||
|
|||
for (auto const& stateProbabilityPair : *currentTargetStates) { |
|||
// Compute the new state under the current update and add it to the set of new target states.
|
|||
CompressedState newTargetState = applyUpdate(stateProbabilityPair.first, update); |
|||
newTargetStates->emplace(newTargetState, stateProbabilityPair.second * evaluator.asRational(update.getLikelihoodExpression())); |
|||
} |
|||
} |
|||
|
|||
// If there is one more command to come, shift the target states one time step back.
|
|||
if (i < iteratorList.size() - 1) { |
|||
delete currentTargetStates; |
|||
currentTargetStates = newTargetStates; |
|||
newTargetStates = new boost::container::flat_map<CompressedState, ValueType>(); |
|||
} |
|||
} |
|||
|
|||
// At this point, we applied all commands of the current command combination and newTargetStates
|
|||
// contains all target states and their respective probabilities. That means we are now ready to
|
|||
// add the choice to the list of transitions.
|
|||
result.push_back(Choice<ValueType>(actionIndex)); |
|||
|
|||
// Now create the actual distribution.
|
|||
Choice<ValueType>& choice = result.back(); |
|||
|
|||
// Remember the command labels only if we were asked to.
|
|||
if (buildChoiceLabeling) { |
|||
// Add the labels of all commands to this choice.
|
|||
for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) { |
|||
choice.addChoiceLabel(iteratorList[i]->get().getGlobalIndex()); |
|||
} |
|||
} |
|||
|
|||
// Add the probabilities/rates to the newly created choice.
|
|||
ValueType probabilitySum = storm::utility::zero<ValueType>(); |
|||
for (auto const& stateProbabilityPair : *newTargetStates) { |
|||
StateType actualIndex = stateToIdCallback(stateProbabilityPair.first); |
|||
choice.addProbability(actualIndex, stateProbabilityPair.second); |
|||
probabilitySum += stateProbabilityPair.second; |
|||
} |
|||
|
|||
// Check that the resulting distribution is in fact a distribution.
|
|||
STORM_LOG_THROW(!program.isDiscreteTimeModel() || !comparator.isConstant(probabilitySum) || comparator.isOne(probabilitySum), storm::exceptions::WrongFormatException, "Sum of update probabilities do not some to one for some command (actually sum to " << probabilitySum << ")."); |
|||
|
|||
// Create the state-action reward for the newly created choice.
|
|||
for (auto const& rewardModel : selectedRewardModels) { |
|||
ValueType stateActionRewardValue = storm::utility::zero<ValueType>(); |
|||
if (rewardModel.get().hasStateActionRewards()) { |
|||
for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) { |
|||
if (stateActionReward.getActionIndex() == choice.getActionIndex() && evaluator.asBool(stateActionReward.getStatePredicateExpression())) { |
|||
stateActionRewardValue += ValueType(evaluator.asRational(stateActionReward.getRewardValueExpression())) * choice.getTotalMass(); |
|||
} |
|||
} |
|||
} |
|||
choice.addChoiceReward(stateActionRewardValue); |
|||
} |
|||
|
|||
// Dispose of the temporary maps.
|
|||
delete currentTargetStates; |
|||
delete newTargetStates; |
|||
|
|||
// Now, check whether there is one more command combination to consider.
|
|||
bool movedIterator = false; |
|||
for (int_fast64_t j = iteratorList.size() - 1; j >= 0; --j) { |
|||
++iteratorList[j]; |
|||
if (iteratorList[j] != activeCommandList[j].end()) { |
|||
movedIterator = true; |
|||
} else { |
|||
// Reset the iterator to the beginning of the list.
|
|||
iteratorList[j] = activeCommandList[j].begin(); |
|||
} |
|||
} |
|||
|
|||
done = !movedIterator; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
template class PrismNextStateGenerator<double>; |
|||
template class PrismNextStateGenerator<storm::RationalFunction>; |
|||
} |
|||
} |
@ -0,0 +1,108 @@ |
|||
#ifndef STORM_GENERATOR_PRISMNEXTSTATEGENERATOR_H_ |
|||
#define STORM_GENERATOR_PRISMNEXTSTATEGENERATOR_H_ |
|||
|
|||
#include "src/generator/NextStateGenerator.h" |
|||
#include "src/generator/VariableInformation.h" |
|||
|
|||
#include "src/storage/prism/Program.h" |
|||
#include "src/storage/expressions/ExpressionEvaluator.h" |
|||
|
|||
#include "src/utility/ConstantsComparator.h" |
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType, typename StateType = uint32_t> |
|||
class PrismNextStateGenerator : public NextStateGenerator<ValueType, StateType> { |
|||
public: |
|||
typedef typename NextStateGenerator<ValueType, StateType>::StateToIdCallback StateToIdCallback; |
|||
|
|||
PrismNextStateGenerator(storm::prism::Program const& program, VariableInformation const& variableInformation, bool buildChoiceLabeling); |
|||
|
|||
/*! |
|||
* Adds a reward model to the list of selected reward models () |
|||
*/ |
|||
void addRewardModel(storm::prism::RewardModel const& rewardModel); |
|||
|
|||
/*! |
|||
* Sets an expression such that if it evaluates to true in a state, prevents the exploration. |
|||
*/ |
|||
void setTerminalExpression(storm::expressions::Expression const& terminalExpression); |
|||
|
|||
virtual bool isDeterministicModel() const override; |
|||
virtual std::vector<StateType> getInitialStates(StateToIdCallback const& stateToIdCallback) override; |
|||
virtual StateBehavior<ValueType, StateType> expand(CompressedState const& state, StateToIdCallback const& stateToIdCallback) 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::prism::Update const& update); |
|||
|
|||
/*! |
|||
* Retrieves all commands that are labeled with the given label and enabled in the given state, grouped by |
|||
* modules. |
|||
* |
|||
* This function will iterate over all modules and retrieve all commands that are labeled with the given |
|||
* action and active (i.e. enabled) in the current state. The result is a list of lists of commands in which |
|||
* the inner lists contain all commands of exactly one module. If a module does not have *any* (including |
|||
* disabled) commands, there will not be a list of commands of that module in the result. If, however, the |
|||
* module has a command with a relevant label, but no enabled one, nothing is returned to indicate that there |
|||
* is no legal transition possible. |
|||
* |
|||
* @param The program in which to search for active commands. |
|||
* @param state The current state. |
|||
* @param actionIndex The index of the action label to select. |
|||
* @return A list of lists of active commands or nothing. |
|||
*/ |
|||
boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> getActiveCommandsByActionIndex(uint_fast64_t const& actionIndex); |
|||
|
|||
/*! |
|||
* Retrieves all unlabeled choices possible from the given state. |
|||
* |
|||
* @param state The state for which to retrieve the unlabeled choices. |
|||
* @return The unlabeled choices of the state. |
|||
*/ |
|||
std::vector<Choice<ValueType>> getUnlabeledChoices(CompressedState const& state, StateToIdCallback stateToIdCallback); |
|||
|
|||
/*! |
|||
* Retrieves all labeled choices possible from the given state. |
|||
* |
|||
* @param state The state for which to retrieve the unlabeled choices. |
|||
* @return The labeled choices of the state. |
|||
*/ |
|||
std::vector<Choice<ValueType>> getLabeledChoices(CompressedState const& state, StateToIdCallback stateToIdCallback); |
|||
|
|||
// The program used for the generation of next states. |
|||
storm::prism::Program const& program; |
|||
|
|||
// The reward models that need to be considered. |
|||
std::vector<std::reference_wrapper<storm::prism::RewardModel const>> selectedRewardModels; |
|||
|
|||
// A flag that stores whether at least one of the selected reward models has state-action rewards. |
|||
bool hasStateActionRewards; |
|||
|
|||
// A flag that stores whether or not to build the choice labeling. |
|||
bool buildChoiceLabeling; |
|||
|
|||
// An optional expression that governs which states must not be explored. |
|||
boost::optional<storm::expressions::Expression> terminalExpression; |
|||
|
|||
// Information about how the variables are packed. |
|||
VariableInformation const& variableInformation; |
|||
|
|||
// An evaluator used to evaluate expressions. |
|||
storm::expressions::ExpressionEvaluator<ValueType> evaluator; |
|||
|
|||
// A comparator used to compare constants. |
|||
storm::utility::ConstantsComparator<ValueType> comparator; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_PRISMNEXTSTATEGENERATOR_H_ */ |
@ -0,0 +1,50 @@ |
|||
#include "src/generator/PrismStateLabelingGenerator.h"
|
|||
|
|||
#include "src/generator/CompressedState.h"
|
|||
|
|||
#include "src/storage/expressions/ExpressionEvaluator.h"
|
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
PrismStateLabelingGenerator<ValueType, StateType>::PrismStateLabelingGenerator(storm::prism::Program const& program, VariableInformation const& variableInformation) : program(program), variableInformation(variableInformation) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
storm::models::sparse::StateLabeling PrismStateLabelingGenerator<ValueType, StateType>::generate(storm::storage::BitVectorHashMap<StateType> const& states, std::vector<StateType> const& initialStateIndices) { |
|||
std::vector<storm::prism::Label> const& labels = program.getLabels(); |
|||
|
|||
storm::expressions::ExpressionEvaluator<ValueType> evaluator(program.getManager()); |
|||
storm::models::sparse::StateLabeling result(states.size()); |
|||
|
|||
// Initialize labeling.
|
|||
for (auto const& label : labels) { |
|||
result.addLabel(label.getName()); |
|||
} |
|||
for (auto const& stateIndexPair : states) { |
|||
unpackStateIntoEvaluator(stateIndexPair.first, variableInformation, evaluator); |
|||
|
|||
for (auto const& label : labels) { |
|||
// Add label to state, if the corresponding expression is true.
|
|||
if (evaluator.asBool(label.getStatePredicateExpression())) { |
|||
result.addLabelToState(label.getName(), stateIndexPair.second); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Also label the initial state with the special label "init".
|
|||
result.addLabel("init"); |
|||
for (auto index : initialStateIndices) { |
|||
result.addLabelToState("init", index); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
template class PrismStateLabelingGenerator<double, uint32_t>; |
|||
template class PrismStateLabelingGenerator<storm::RationalFunction, uint32_t>; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,31 @@ |
|||
#ifndef STORM_GENERATOR_PRISMSTATELABELINGGENERATOR_H_ |
|||
#define STORM_GENERATOR_PRISMSTATELABELINGGENERATOR_H_ |
|||
|
|||
#include "src/generator/StateLabelingGenerator.h" |
|||
|
|||
#include "src/generator/VariableInformation.h" |
|||
|
|||
#include "src/storage/prism/Program.h" |
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType, typename StateType = uint32_t> |
|||
class PrismStateLabelingGenerator : public StateLabelingGenerator<StateType> { |
|||
public: |
|||
PrismStateLabelingGenerator(storm::prism::Program const& program, VariableInformation const& variableInformation); |
|||
|
|||
virtual storm::models::sparse::StateLabeling generate(storm::storage::BitVectorHashMap<StateType> const& states, std::vector<StateType> const& initialStateIndices = {}) override; |
|||
|
|||
private: |
|||
// The program for which to generate the labels. |
|||
storm::prism::Program const& program; |
|||
|
|||
// Information about how the variables are packed. |
|||
VariableInformation const& variableInformation; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_PRISMSTATELABELINGGENERATOR_H_ */ |
@ -0,0 +1,57 @@ |
|||
#include "src/generator/StateBehavior.h"
|
|||
|
|||
#include "src/adapters/CarlAdapter.h"
|
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
StateBehavior<ValueType, StateType>::StateBehavior() : expanded(false) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void StateBehavior<ValueType, StateType>::addChoice(Choice<ValueType, StateType>&& choice) { |
|||
choices.push_back(std::move(choice)); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void StateBehavior<ValueType, StateType>::addStateReward(ValueType const& stateReward) { |
|||
stateRewards.push_back(stateReward); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
void StateBehavior<ValueType, StateType>::setExpanded(bool newValue) { |
|||
this->expanded = newValue; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
bool StateBehavior<ValueType, StateType>::wasExpanded() const { |
|||
return expanded; |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
bool StateBehavior<ValueType, StateType>::empty() const { |
|||
return choices.empty(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
typename std::vector<Choice<ValueType, StateType>>::const_iterator StateBehavior<ValueType, StateType>::begin() const { |
|||
return choices.begin(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
typename std::vector<Choice<ValueType, StateType>>::const_iterator StateBehavior<ValueType, StateType>::end() const { |
|||
return choices.end(); |
|||
} |
|||
|
|||
template<typename ValueType, typename StateType> |
|||
std::vector<ValueType> const& StateBehavior<ValueType, StateType>::getStateRewards() const { |
|||
return stateRewards; |
|||
} |
|||
|
|||
template class StateBehavior<double>; |
|||
template class StateBehavior<storm::RationalFunction>; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,73 @@ |
|||
#ifndef STORM_GENERATOR_PRISM_STATEBEHAVIOR_H_ |
|||
#define STORM_GENERATOR_PRISM_STATEBEHAVIOR_H_ |
|||
|
|||
#include <cstdint> |
|||
|
|||
#include "src/generator/Choice.h" |
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename ValueType, typename StateType = uint32_t> |
|||
class StateBehavior { |
|||
public: |
|||
/*! |
|||
* Creates an empty behavior, i.e. the state was not yet expanded. |
|||
*/ |
|||
StateBehavior(); |
|||
|
|||
/*! |
|||
* Adds the given choice to the behavior of the state. |
|||
*/ |
|||
void addChoice(Choice<ValueType, StateType>&& choice); |
|||
|
|||
/*! |
|||
* Adds the given state reward to the behavior of the state. |
|||
*/ |
|||
void addStateReward(ValueType const& stateReward); |
|||
|
|||
/*! |
|||
* Sets whether the state was expanded. |
|||
*/ |
|||
void setExpanded(bool newValue = true); |
|||
|
|||
/*! |
|||
* Retrieves whether the state was expanded. |
|||
*/ |
|||
bool wasExpanded() const; |
|||
|
|||
/*! |
|||
* Retrieves whether the behavior is empty in the sense that there are no available choices. |
|||
*/ |
|||
bool empty() const; |
|||
|
|||
/*! |
|||
* Retrieves an iterator to the choices available in the behavior. |
|||
*/ |
|||
typename std::vector<Choice<ValueType, StateType>>::const_iterator begin() const; |
|||
|
|||
/*! |
|||
* Retrieves an iterator past the choices available in the behavior. |
|||
*/ |
|||
typename std::vector<Choice<ValueType, StateType>>::const_iterator end() const; |
|||
|
|||
/*! |
|||
* Retrieves the list of state rewards under selected reward models. |
|||
*/ |
|||
std::vector<ValueType> const& getStateRewards() const; |
|||
|
|||
private: |
|||
// The choices available in the state. |
|||
std::vector<Choice<ValueType, StateType>> choices; |
|||
|
|||
// The state rewards (under the different, selected reward models) of the state. |
|||
std::vector<ValueType> stateRewards; |
|||
|
|||
// A flag indicating whether the state was actually expanded. |
|||
bool expanded; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_PRISM_STATEBEHAVIOR_H_ */ |
@ -0,0 +1,20 @@ |
|||
#ifndef STORM_GENERATOR_STATELABELINGGENERATOR_H_ |
|||
#define STORM_GENERATOR_STATELABELINGGENERATOR_H_ |
|||
|
|||
#include "src/models/sparse/StateLabeling.h" |
|||
|
|||
#include "src/storage/BitVectorHashMap.h" |
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template<typename StateType = uint32_t> |
|||
class StateLabelingGenerator { |
|||
public: |
|||
virtual storm::models::sparse::StateLabeling generate(storm::storage::BitVectorHashMap<StateType> const& states, std::vector<StateType> const& initialStateIndices = {}) = 0; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_STATELABELINGGENERATOR_H_ */ |
@ -0,0 +1,77 @@ |
|||
#include "src/generator/VariableInformation.h"
|
|||
|
|||
#include "src/utility/macros.h"
|
|||
#include "src/exceptions/InvalidArgumentException.h"
|
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
BooleanVariableInformation::BooleanVariableInformation(storm::expressions::Variable const& variable, bool initialValue, uint_fast64_t bitOffset) : variable(variable), initialValue(initialValue), bitOffset(bitOffset) { |
|||
// 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) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
VariableInformation::VariableInformation(storm::prism::Program const& program) : totalBitOffset(0) { |
|||
for (auto const& booleanVariable : program.getGlobalBooleanVariables()) { |
|||
booleanVariables.emplace_back(booleanVariable.getExpressionVariable(), booleanVariable.getInitialValueExpression().evaluateAsBool(), totalBitOffset); |
|||
++totalBitOffset; |
|||
booleanVariableToIndexMap[booleanVariable.getExpressionVariable()] = booleanVariables.size() - 1; |
|||
} |
|||
for (auto const& integerVariable : program.getGlobalIntegerVariables()) { |
|||
int_fast64_t lowerBound = integerVariable.getLowerBoundExpression().evaluateAsInt(); |
|||
int_fast64_t upperBound = integerVariable.getUpperBoundExpression().evaluateAsInt(); |
|||
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); |
|||
totalBitOffset += bitwidth; |
|||
integerVariableToIndexMap[integerVariable.getExpressionVariable()] = integerVariables.size() - 1; |
|||
} |
|||
for (auto const& module : program.getModules()) { |
|||
for (auto const& booleanVariable : module.getBooleanVariables()) { |
|||
booleanVariables.emplace_back(booleanVariable.getExpressionVariable(), booleanVariable.getInitialValueExpression().evaluateAsBool(), totalBitOffset); |
|||
++totalBitOffset; |
|||
booleanVariableToIndexMap[booleanVariable.getExpressionVariable()] = booleanVariables.size() - 1; |
|||
} |
|||
for (auto const& integerVariable : module.getIntegerVariables()) { |
|||
int_fast64_t lowerBound = integerVariable.getLowerBoundExpression().evaluateAsInt(); |
|||
int_fast64_t upperBound = integerVariable.getUpperBoundExpression().evaluateAsInt(); |
|||
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); |
|||
totalBitOffset += bitwidth; |
|||
integerVariableToIndexMap[integerVariable.getExpressionVariable()] = integerVariables.size() - 1; |
|||
} |
|||
} |
|||
} |
|||
|
|||
uint_fast64_t VariableInformation::getTotalBitOffset(bool roundTo64Bit) const { |
|||
uint_fast64_t result = totalBitOffset; |
|||
if (roundTo64Bit) { |
|||
result = ((result >> 6) + 1) << 6; |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
auto const& integerIndex = integerVariableToIndexMap.find(variable); |
|||
if (integerIndex != integerVariableToIndexMap.end()) { |
|||
return integerVariables[integerIndex->second].bitOffset; |
|||
} |
|||
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; |
|||
} |
|||
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Cannot look-up bit width of unknown variable."); |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,75 @@ |
|||
#ifndef STORM_GENERATOR_VARIABLEINFORMATION_H_ |
|||
#define STORM_GENERATOR_VARIABLEINFORMATION_H_ |
|||
|
|||
#include <vector> |
|||
#include <boost/container/flat_map.hpp> |
|||
|
|||
#include "src/storage/expressions/Variable.h" |
|||
#include "src/storage/prism/Program.h" |
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
// A structure storing information about the boolean variables of the program. |
|||
struct BooleanVariableInformation { |
|||
BooleanVariableInformation(storm::expressions::Variable const& variable, bool initialValue, uint_fast64_t bitOffset); |
|||
|
|||
// The boolean variable. |
|||
storm::expressions::Variable variable; |
|||
|
|||
// Its initial value. |
|||
bool initialValue; |
|||
|
|||
// Its bit offset in the compressed state. |
|||
uint_fast64_t bitOffset; |
|||
}; |
|||
|
|||
// A structure storing information about the integer variables of the program. |
|||
struct 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); |
|||
|
|||
// The integer variable. |
|||
storm::expressions::Variable variable; |
|||
|
|||
// Its initial value. |
|||
int_fast64_t initialValue; |
|||
|
|||
// The lower bound of its range. |
|||
int_fast64_t lowerBound; |
|||
|
|||
// The upper bound of its range. |
|||
int_fast64_t upperBound; |
|||
|
|||
// Its bit offset in the compressed state. |
|||
uint_fast64_t bitOffset; |
|||
|
|||
// Its bit width in the compressed state. |
|||
uint_fast64_t bitWidth; |
|||
}; |
|||
|
|||
// A structure storing information about the used variables of the program. |
|||
struct VariableInformation { |
|||
VariableInformation() = default; |
|||
VariableInformation(storm::prism::Program const& program); |
|||
uint_fast64_t getTotalBitOffset(bool roundTo64Bit = false) const; |
|||
|
|||
// Provide methods to access the bit offset and width of variables in the compressed state. |
|||
uint_fast64_t getBitOffset(storm::expressions::Variable const& variable) const; |
|||
uint_fast64_t getBitWidth(storm::expressions::Variable const& variable) const; |
|||
|
|||
// The total bit offset over all variables. |
|||
uint_fast64_t totalBitOffset; |
|||
|
|||
// The known boolean variables. |
|||
boost::container::flat_map<storm::expressions::Variable, uint_fast64_t> booleanVariableToIndexMap; |
|||
std::vector<BooleanVariableInformation> booleanVariables; |
|||
|
|||
// The known integer variables. |
|||
boost::container::flat_map<storm::expressions::Variable, uint_fast64_t> integerVariableToIndexMap; |
|||
std::vector<IntegerVariableInformation> integerVariables; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_GENERATOR_VARIABLEINFORMATION_H_ */ |
Reference in new issue
xxxxxxxxxx