Browse Source

Added globally unique indexes to updates in IR. Finalized support for labeled values in ExplicitModelAdapter. Modified tests to comply with the new usage of ExplicitModelAdapter.

Former-commit-id: f6d5a33d6d
main
dehnert 12 years ago
parent
commit
84f1b192b4
  1. 397
      src/adapters/ExplicitModelAdapter.cpp
  2. 183
      src/adapters/ExplicitModelAdapter.h
  3. 2
      src/ir/Command.cpp
  4. 12
      src/ir/Update.cpp
  5. 20
      src/ir/Update.h
  6. 8
      src/parser/prismparser/PrismGrammar.cpp
  7. 15
      src/parser/prismparser/PrismGrammar.h
  8. 7
      src/parser/prismparser/VariableState.cpp
  9. 20
      src/parser/prismparser/VariableState.h
  10. 38
      src/storage/LabeledValues.h
  11. 9
      test/functional/parser/ParsePrismTest.cpp

397
src/adapters/ExplicitModelAdapter.cpp

@ -1,403 +1,6 @@
#include "src/adapters/ExplicitModelAdapter.h"
#include "src/storage/SparseMatrix.h"
#include "src/settings/Settings.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/ir/Program.h"
#include "src/ir/RewardModel.h"
#include "src/ir/StateReward.h"
#include "src/ir/TransitionReward.h"
#include "src/models/AbstractModel.h"
#include "src/models/Dtmc.h"
#include "src/models/Ctmc.h"
#include "src/models/Mdp.h"
#include "src/models/Ctmdp.h"
#include <algorithm>
#include <functional>
#include <boost/algorithm/string.hpp>
#include <sstream>
#include <ostream>
bool ExplicitModelAdapterOptionsRegistered = storm::settings::Settings::registerNewModule([] (storm::settings::Settings* instance) -> bool {
instance->addOption(storm::settings::OptionBuilder("ExplicitModelAdapter", "constants", "", "Specifies the constant replacements to use in Explicit Models").addArgument(storm::settings::ArgumentBuilder::createStringArgument("constantString", "A comma separated list of constants and their value, e.g. a=1,b=2,c=3").setDefaultValueString("").build()).build());
return true;
});
namespace storm {
namespace adapters {
// std::vector<double> ExplicitModelAdapter::getStateRewards(std::vector<storm::ir::StateReward> const& rewards) {
// std::vector<double> result(this->allStates.size());
// for (uint_fast64_t index = 0; index < this->allStates.size(); index++) {
// result[index] = 0;
// for (auto const& reward : rewards) {
// // Add this reward to the state if the state is included in the state reward.
// if (reward.getStatePredicate()->getValueAsBool(this->allStates[index]) == true) {
// result[index] += reward.getRewardValue()->getValueAsDouble(this->allStates[index]);
// }
// }
// }
// return result;
// }
// storm::models::AtomicPropositionsLabeling ExplicitModelAdapter::getStateLabeling(std::map<std::string, std::shared_ptr<storm::ir::expressions::BaseExpression>> labels) {
// storm::models::AtomicPropositionsLabeling results(this->allStates.size(), labels.size() + 1);
// // Initialize labeling.
// for (auto const& labelExpressionPair : labels) {
// results.addAtomicProposition(labelExpressionPair.first);
// }
// for (uint_fast64_t index = 0; index < this->allStates.size(); index++) {
// for (auto const& labelExpressionPair: labels) {
// // Add label to state, if the corresponding expression is true.
// if (labelExpressionPair.second->getValueAsBool(this->allStates[index])) {
// results.addAtomicPropositionToState(labelExpressionPair.first, index);
// }
// }
// }
//
// // Also label the initial state with the special label "init".
// results.addAtomicProposition("init");
// StateType* initialState = this->getInitialState();
// uint_fast64_t initialIndex = this->stateToIndexMap[initialState];
// results.addAtomicPropositionToState("init", initialIndex);
// delete initialState;
//
// return results;
// }
// boost::optional<std::vector<std::list<storm::ir::Command>>> ExplicitModelAdapter::getActiveCommandsByAction(StateType const* state, std::string const& action) {
// boost::optional<std::vector<std::list<storm::ir::Command>>> result((std::vector<std::list<storm::ir::Command>>()));
//
// // Iterate over all modules.
// for (uint_fast64_t i = 0; i < this->program.getNumberOfModules(); ++i) {
// storm::ir::Module const& module = this->program.getModule(i);
//
// // If the module has no command labeled with the given action, we can skip this module.
// if (!module.hasAction(action)) {
// continue;
// }
//
// std::set<uint_fast64_t> const& commandIndices = module.getCommandsByAction(action);
// std::list<storm::ir::Command> 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::ir::Command const& command = module.getCommand(commandIndex);
// if (command.getGuard()->getValueAsBool(state)) {
// 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::list<storm::ir::Command>>>();
// }
//
// result.get().push_back(std::move(commands));
// }
// return result;
// }
// void ExplicitModelAdapter::addUnlabeledTransitions(uint_fast64_t stateIndex, std::list<std::pair<std::pair<std::string, std::list<uint_fast64_t>>, std::map<uint_fast64_t, double>>>& transitionList) {
// StateType const* state = this->allStates[stateIndex];
//
// // Iterate over all modules.
// for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
// storm::ir::Module const& module = program.getModule(i);
//
// // Iterate over all commands.
// for (uint_fast64_t j = 0; j < module.getNumberOfCommands(); ++j) {
// storm::ir::Command const& command = module.getCommand(j);
//
// // Only consider unlabeled commands.
// if (command.getActionName() != "") continue;
// // Skip the command, if it is not enabled.
// if (!command.getGuard()->getValueAsBool(state)) continue;
//
// // Add a new choice for the state.
// transitionList.emplace_back();
//
// // Add the index of the current command to the labeling of the choice.
// transitionList.back().first.second.emplace_back(command.getGlobalIndex());
//
// // Create an alias for all target states for convenience.
// std::map<uint_fast64_t, double>& targetStates = transitionList.back().second;
//
// // Also keep track of the total probability leaving the state.
// double probabilitySum = 0;
//
// // Iterate over all updates of the current command.
// for (uint_fast64_t k = 0; k < command.getNumberOfUpdates(); ++k) {
// storm::ir::Update const& update = command.getUpdate(k);
//
// // Obtain target state index.
// uint_fast64_t newTargetStateIndex = this->getOrAddStateIndex(this->applyUpdate(state, update));
//
// probabilitySum += update.getLikelihoodExpression()->getValueAsDouble(state);
//
// // Check, if we already saw this state in another update and, if so, add up probabilities.
// auto stateIt = targetStates.find(newTargetStateIndex);
// if (stateIt == targetStates.end()) {
// targetStates[newTargetStateIndex] = update.getLikelihoodExpression()->getValueAsDouble(state);
// this->numberOfTransitions++;
// } else {
// targetStates[newTargetStateIndex] += update.getLikelihoodExpression()->getValueAsDouble(state);
// }
// }
//
// if (std::abs(1 - probabilitySum) > this->precision) {
// LOG4CPLUS_ERROR(logger, "Sum of update probabilities should be one for command:\n\t" << command.toString());
// throw storm::exceptions::WrongFormatException() << "Sum of update probabilities should be one for command:\n\t" << command.toString();
// }
// }
// }
// }
// void ExplicitModelAdapter::addLabeledTransitions(uint_fast64_t stateIndex, std::list<std::pair<std::pair<std::string, std::list<uint_fast64_t>>, std::map<uint_fast64_t, double>>>& transitionList) {
// for (std::string const& action : this->program.getActions()) {
// StateType* currentState = this->allStates[stateIndex];
// boost::optional<std::vector<std::list<storm::ir::Command>>> optionalActiveCommandLists = this->getActiveCommandsByAction(currentState, action);
//
// // Only process this action label, if there is at least one feasible solution.
// if (optionalActiveCommandLists) {
// std::vector<std::list<storm::ir::Command>> const& activeCommandList = optionalActiveCommandLists.get();
// std::vector<std::list<storm::ir::Command>::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) {
// std::unordered_map<StateType*, double, StateHash, StateCompare>* currentTargetStates = new std::unordered_map<StateType*, double, StateHash, StateCompare>();
// std::unordered_map<StateType*, double, StateHash, StateCompare>* newTargetStates = new std::unordered_map<StateType*, double, StateHash, StateCompare>();
// (*currentTargetStates)[new StateType(*currentState)] = 1.0;
//
// // FIXME: This does not check whether a global variable is written multiple times. While the
// // behaviour for this is undefined anyway, a warning should be issued in that case.
// double probabilitySum = 0;
// for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) {
// storm::ir::Command const& command = *iteratorList[i];
//
// for (uint_fast64_t j = 0; j < command.getNumberOfUpdates(); ++j) {
// storm::ir::Update const& update = command.getUpdate(j);
//
// for (auto const& stateProbabilityPair : *currentTargetStates) {
// StateType* newTargetState = this->applyUpdate(stateProbabilityPair.first, currentState, update);
// probabilitySum += stateProbabilityPair.second * update.getLikelihoodExpression()->getValueAsDouble(currentState);
//
// auto existingStateProbabilityPair = newTargetStates->find(newTargetState);
// if (existingStateProbabilityPair == newTargetStates->end()) {
// (*newTargetStates)[newTargetState] = stateProbabilityPair.second * update.getLikelihoodExpression()->getValueAsDouble(currentState);
// } else {
// existingStateProbabilityPair->second += stateProbabilityPair.second * update.getLikelihoodExpression()->getValueAsDouble(currentState);
// }
// }
// }
//
// // If there is one more command to come, shift the target states one time step back.
// if (i < iteratorList.size() - 1) {
// for (auto const& stateProbabilityPair : *currentTargetStates) {
// delete stateProbabilityPair.first;
// }
// delete currentTargetStates;
// currentTargetStates = newTargetStates;
// newTargetStates = new std::unordered_map<StateType*, double, StateHash, StateCompare>();
// }
// }
//
// // 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.
// transitionList.emplace_back(std::make_pair(std::make_pair(action, std::list<uint_fast64_t>()), std::map<uint_fast64_t, double>()));
//
// // Add the commands that were involved in creating this distribution to the labeling.
// for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) {
// transitionList.back().first.second.push_back(iteratorList[i]->getGlobalIndex());
// }
//
// // Now create the actual distribution.
// std::map<uint_fast64_t, double>& states = transitionList.back().second;
// for (auto const& stateProbabilityPair : *newTargetStates) {
// uint_fast64_t newStateIndex = this->getOrAddStateIndex(stateProbabilityPair.first);
// states[newStateIndex] = stateProbabilityPair.second;
// }
// this->numberOfTransitions += states.size();
//
// // 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;
// }
// }
// }
// }
// storm::storage::SparseMatrix<double> ExplicitModelAdapter::buildDeterministicMatrix() {
// // Note: this->numberOfTransitions may be meaningless here, as we need to combine all nondeterministic
// // choices for all states into one determinstic one, which might reduce the number of transitions.
// // Hence, we compute the correct number now.
// uint_fast64_t numberOfTransitions = 0;
// for (uint_fast64_t state = 0; state < this->allStates.size(); ++state) {
// // Collect all target nodes in a set to get the number of distinct nodes.
// std::set<uint_fast64_t> set;
// for (auto const& choice : transitionMap[state]) {
// for (auto const& targetStates : choice.second) {
// set.insert(targetStates.first);
// }
// }
// numberOfTransitions += set.size();
// }
//
// LOG4CPLUS_INFO(logger, "Building deterministic transition matrix: " << allStates.size() << " x " << allStates.size() << " with " << numberOfTransitions << " transitions.");
//
// this->choiceLabeling.clear();
// this->choiceLabeling.reserve(allStates.size());
//
// // Now build the actual matrix.
// storm::storage::SparseMatrix<double> result(allStates.size());
// result.initialize(numberOfTransitions);
// if ((this->rewardModel != nullptr) && (this->rewardModel->hasTransitionRewards())) {
// this->transitionRewards.reset(std::move(storm::storage::SparseMatrix<double>(allStates.size())));
// this->transitionRewards.get().initialize(numberOfTransitions);
// }
//
// for (uint_fast64_t state = 0; state < this->allStates.size(); state++) {
// if (transitionMap[state].size() > 1) {
// LOG4CPLUS_WARN(logger, "State " << state << " has " << transitionMap[state].size() << " overlapping guards in deterministic model.");
// }
//
// // Combine nondeterministic choices into one by weighting them equally.
// std::map<uint_fast64_t, double> map;
// std::map<uint_fast64_t, double> rewardMap;
// std::list<uint_fast64_t> commandList;
// for (auto const& choice : transitionMap[state]) {
// commandList.insert(commandList.end(), choice.first.second.begin(), choice.first.second.end());
// for (auto const& targetStates : choice.second) {
// map[targetStates.first] += targetStates.second;
// if ((this->rewardModel != nullptr) && (this->rewardModel->hasTransitionRewards())) {
// for (auto const& reward : this->rewardModel->getTransitionRewards()) {
// if (reward.getStatePredicate()->getValueAsBool(this->allStates[state]) == true) {
// rewardMap[targetStates.first] += reward.getRewardValue()->getValueAsDouble(this->allStates[state]);
// }
// }
// }
// }
// }
// // Make sure that each command is only added once to the label of the transition.
// commandList.sort();
// commandList.unique();
//
// // Add the labeling for the behaviour of the current state.
// this->choiceLabeling.emplace_back(std::move(commandList));
//
// // Scale probabilities by number of choices.
// double factor = 1.0 / transitionMap[state].size();
// for (auto& targetStates : map) {
// result.addNextValue(state, targetStates.first, targetStates.second * factor);
// if ((this->rewardModel != nullptr) && (this->rewardModel->hasTransitionRewards())) {
// this->transitionRewards.get().addNextValue(state, targetStates.first, rewardMap[targetStates.first] * factor);
// }
// }
//
// }
//
// result.finalize();
// return result;
// }
// storm::storage::SparseMatrix<double> ExplicitModelAdapter::buildNondeterministicMatrix() {
// LOG4CPLUS_INFO(logger, "Building nondeterministic transition matrix: " << this->numberOfChoices << " x " << allStates.size() << " with " << this->numberOfTransitions << " transitions.");
// storm::storage::SparseMatrix<double> result(this->numberOfChoices, allStates.size());
// result.initialize(this->numberOfTransitions);
// if ((this->rewardModel != nullptr) && (this->rewardModel->hasTransitionRewards())) {
// this->transitionRewards.reset(storm::storage::SparseMatrix<double>(this->numberOfChoices, allStates.size()));
// this->transitionRewards.get().initialize(this->numberOfTransitions);
// }
// this->choiceIndices.clear();
// this->choiceIndices.reserve(allStates.size() + 1);
// this->choiceLabeling.clear();
// this->choiceLabeling.reserve(allStates.size());
//
// // Now build the actual matrix.
// uint_fast64_t nextRow = 0;
// this->choiceIndices.push_back(0);
// for (uint_fast64_t state = 0; state < this->allStates.size(); state++) {
// this->choiceIndices.push_back(this->choiceIndices[state] + transitionMap[state].size());
// for (auto const& choice : transitionMap[state]) {
// this->choiceLabeling.emplace_back(std::move(choice.first.second));
// for (auto const& targetStates : choice.second) {
// result.addNextValue(nextRow, targetStates.first, targetStates.second);
// if ((this->rewardModel != nullptr) && (this->rewardModel->hasTransitionRewards())) {
// double rewardValue = 0;
// for (auto const& reward : this->rewardModel->getTransitionRewards()) {
// if (reward.getStatePredicate()->getValueAsBool(this->allStates[state]) == true) {
// rewardValue = reward.getRewardValue()->getValueAsDouble(this->allStates[state]);
// }
// }
// this->transitionRewards.get().addNextValue(nextRow, targetStates.first, rewardValue);
// }
// }
// ++nextRow;
// }
// }
//
// result.finalize();
// return result;
// }
// void ExplicitModelAdapter::buildTransitionMap() {
// LOG4CPLUS_DEBUG(logger, "Creating transition map from program.");
// this->clearInternalState();
// this->allStates.clear();
// this->allStates.push_back(this->getInitialState());
// stateToIndexMap[this->allStates[0]] = 0;
//
// for (uint_fast64_t state = 0; state < this->allStates.size(); ++state) {
// this->addUnlabeledTransitions(state, this->transitionMap[state]);
// this->addLabeledTransitions(state, this->transitionMap[state]);
//
// this->numberOfChoices += this->transitionMap[state].size();
//
// // Check whether the current state is a deadlock state and treat it accordingly.
// if (this->transitionMap[state].size() == 0) {
// if (storm::settings::Settings::getInstance()->isSet("fixDeadlocks")) {
// ++this->numberOfTransitions;
// ++this->numberOfChoices;
// this->transitionMap[state].emplace_back();
// this->transitionMap[state].back().second[state] = 1;
// } else {
// LOG4CPLUS_ERROR(logger, "Error while creating sparse matrix from probabilistic program: found deadlock state. For fixing these, please provide the appropriate option.");
// throw storm::exceptions::WrongFormatException() << "Error while creating sparse matrix from probabilistic program: found deadlock state. For fixing these, please provide the appropriate option.";
// }
// }
// }
//
// LOG4CPLUS_DEBUG(logger, "Finished creating transition map.");
// }
} // namespace adapters
} // namespace storm

183
src/adapters/ExplicitModelAdapter.h

@ -75,10 +75,20 @@ namespace storm {
// A structure holding information about a particular choice.
template<typename ValueType>
struct Choice {
public:
Choice(std::string const& actionLabel) : distribution(), actionLabel(actionLabel), choiceLabels() {
// Intentionally left empty.
}
/*!
* Returns an iterator to the first element of this choice.
*
* @return An iterator to the first element of this choice.
*/
typename std::map<uint_fast64_t, ValueType>::iterator begin() {
return distribution.begin();
}
/*!
* Returns an iterator to the first element of this choice.
*
@ -88,6 +98,15 @@ namespace storm {
return distribution.cbegin();
}
/*!
* Returns an iterator that points past the elements of this choice.
*
* @return An iterator that points past the elements of this choice.
*/
typename std::map<uint_fast64_t, ValueType>::iterator end() {
return distribution.end();
}
/*!
* Returns an iterator that points past the elements of this choice.
*
@ -97,6 +116,31 @@ namespace storm {
return distribution.cend();
}
/*!
* Returns an iterator to the element with the given key, if there is one. Otherwise, the iterator points to
* distribution.end().
*
* @param value The value to find.
* @return An iterator to the element with the given key, if there is one.
*/
typename std::map<uint_fast64_t, ValueType>::iterator find(uint_fast64_t value) {
return distribution.find(value);
}
/*!
* Inserts the contents of this object to the given output stream.
*
* @param out The stream in which to insert the contents.
*/
friend std::ostream& operator<<(std::ostream& out, Choice<ValueType> const& choice) {
out << "<";
for (auto const& stateProbabilityPair : choice.distribution) {
out << stateProbabilityPair.first << " : " << stateProbabilityPair.second << ", ";
}
out << ">";
return out;
}
/*!
* Adds the given label to the labels associated with this choice.
*
@ -106,6 +150,68 @@ namespace storm {
choiceLabels.insert(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(std::set<uint_fast64_t> const& labelSet) {
for (uint_fast64_t label : labelSet) {
addChoiceLabel(label);
}
}
/*!
* Retrieves the set of labels associated with this choice.
*
* @return The set of labels associated with this choice.
*/
std::set<uint_fast64_t> const& getChoiceLabels() const {
return choiceLabels;
}
/*!
* Retrieves the action label of this choice.
*
* @return The action label of this choice.
*/
std::string const& getActionLabel() const {
return actionLabel;
}
/*!
* Retrieves the entry in the choice that is associated with the given state and creates one if none exists,
* yet.
*
* @param state The state for which to add the entry.
* @return A reference to the entry that is associated with the given state.
*/
ValueType& getOrAddEntry(uint_fast64_t state) {
auto stateProbabilityPair = distribution.find(state);
if (stateProbabilityPair == distribution.end()) {
distribution[state] = ValueType();
}
return distribution.at(state);
}
/*!
* Retrieves the entry in the choice that is associated with the given state and creates one if none exists,
* yet.
*
* @param state The state for which to add the entry.
* @return A reference to the entry that is associated with the given state.
*/
ValueType const& getOrAddEntry(uint_fast64_t state) const {
auto stateProbabilityPair = distribution.find(state);
if (stateProbabilityPair == distribution.end()) {
distribution[state] = ValueType();
}
return distribution.at(state);
}
private:
// The distribution that is associated with the choice.
std::map<uint_fast64_t, ValueType> distribution;
@ -116,25 +222,34 @@ namespace storm {
std::set<uint_fast64_t> choiceLabels;
};
/*!
* Adds the target state and probability to the given choice and ignores the labels. This function overloads with
* other functions to ensure the proper treatment of labels.
*
* @param choice The choice to which to add the target state and probability.
* @param state The target state of the probability.
* @param probability The probability to reach the target state in one step.
* @param labels A set of labels that is supposed to be associated with this state and probability. NOTE: this
* is ignored by this particular function but not by the overloaded functions.
*/
template<typename ValueType>
void addProbabilityToChoice(Choice<ValueType>& choice, uint_fast64_t state, ValueType probability, std::set<uint_fast64_t> const& labels) {
auto stateProbabilityPair = choice.distribution.find(state);
if (stateProbabilityPair == choice.distribution.end()) {
choice.distribution[state] = probability;
} else {
choice.distribution[state] += probability;
}
choice.getOrAddEntry(state) += probability;
}
/*!
* Adds the target state and probability to the given choice and labels it accordingly. This function overloads
* with other functions to ensure the proper treatment of labels.
*
* @param choice The choice to which to add the target state and probability.
* @param state The target state of the probability.
* @param probability The probability to reach the target state in one step.
* @param labels A set of labels that is supposed to be associated with this state and probability.
*/
template<typename ValueType>
void addProbabilityToChoice(Choice<storm::storage::LabeledValues<ValueType>>& choice, uint_fast64_t state, ValueType probability, std::set<uint_fast64_t> const& labels) {
auto stateProbabilityPair = choice.distribution.find(state);
if (stateProbabilityPair == choice.distribution.end()) {
choice.distribution[state] = storm::storage::LabeledValues<ValueType>();
}
choice.distribution[state].addValue(probability);
auto& labeledEntry = choice.getOrAddEntry(state);
labeledEntry.addValue(probability, labels);
}
template<typename ValueType>
@ -794,13 +909,10 @@ namespace storm {
// Obtain target state index.
uint_fast64_t targetStateIndex = stateInformation.stateToIndexMap.at(applyUpdate(variableInformation, currentState, update));
// Check, if we already saw this state in another update and, if so, add up probabilities.
// Update the choice by adding the probability/target state to it.
double probabilityToAdd = update.getLikelihoodExpression()->getValueAsDouble(currentState);
probabilitySum += probabilityToAdd;
std::set<uint_fast64_t> labels;
// FIXME: We have to retrieve the index of the update here, which is currently not possible.
// labels.insert(update.getGlobalIndex());
addProbabilityToChoice(choice, targetStateIndex, probabilityToAdd, labels);
addProbabilityToChoice(choice, targetStateIndex, probabilityToAdd, {update.getGlobalIndex()});
}
// Check that the resulting distribution is in fact a distribution.
@ -952,38 +1064,29 @@ namespace storm {
// Then, based on whether the model is deterministic or not, either add the choices individually
// or compose them to one choice.
if (deterministicModel) {
std::map<uint_fast64_t, ValueType> globalDistribution;
Choice<ValueType> globalChoice("");
std::set<uint_fast64_t> allChoiceLabels;
// Combine all the choices and scale them with the total number of choices of the current state.
for (auto const& choice : allUnlabeledChoices) {
allChoiceLabels.insert(choice.choiceLabels.begin(), choice.choiceLabels.end());
globalChoice.addChoiceLabels(choice.getChoiceLabels());
for (auto const& stateProbabilityPair : choice) {
auto existingStateProbabilityPair = globalDistribution.find(stateProbabilityPair.first);
if (existingStateProbabilityPair == globalDistribution.end()) {
globalDistribution[stateProbabilityPair.first] += stateProbabilityPair.second / totalNumberOfChoices;
} else {
globalDistribution[stateProbabilityPair.first] = stateProbabilityPair.second / totalNumberOfChoices;
}
globalChoice.getOrAddEntry(stateProbabilityPair.first) += stateProbabilityPair.second / totalNumberOfChoices;
}
}
for (auto const& choice : allLabeledChoices) {
globalChoice.addChoiceLabels(choice.getChoiceLabels());
for (auto const& stateProbabilityPair : choice) {
auto existingStateProbabilityPair = globalDistribution.find(stateProbabilityPair.first);
if (existingStateProbabilityPair == globalDistribution.end()) {
globalDistribution[stateProbabilityPair.first] += stateProbabilityPair.second / totalNumberOfChoices;
} else {
globalDistribution[stateProbabilityPair.first] = stateProbabilityPair.second / totalNumberOfChoices;
}
globalChoice.getOrAddEntry(stateProbabilityPair.first) += stateProbabilityPair.second / totalNumberOfChoices;
}
}
// Now add the resulting distribution as the only choice of the current state.
nondeterministicChoiceIndices[currentState] = currentRow;
choiceLabels.push_back(allChoiceLabels);
choiceLabels.push_back(globalChoice.getChoiceLabels());
for (auto const& stateProbabilityPair : globalDistribution) {
for (auto const& stateProbabilityPair : globalChoice) {
transitionMatrix.insertNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
}
@ -995,7 +1098,7 @@ namespace storm {
// First, process all unlabeled choices.
for (auto const& choice : allUnlabeledChoices) {
std::map<uint_fast64_t, ValueType> stateToRewardMap;
choiceLabels.emplace_back(std::move(choice.choiceLabels));
choiceLabels.emplace_back(std::move(choice.getChoiceLabels()));
for (auto const& stateProbabilityPair : choice) {
transitionMatrix.insertNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
@ -1003,7 +1106,7 @@ namespace storm {
// Now add all rewards that match this choice.
for (auto const& transitionReward : transitionRewards) {
if (transitionReward.getActionName() == "" && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) {
stateToRewardMap[stateProbabilityPair.first] += transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState));
stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState)));
}
}
@ -1020,7 +1123,7 @@ namespace storm {
// Then, process all labeled choices.
for (auto const& choice : allLabeledChoices) {
std::map<uint_fast64_t, ValueType> stateToRewardMap;
choiceLabels.emplace_back(std::move(choice.choiceLabels));
choiceLabels.emplace_back(std::move(choice.getChoiceLabels()));
for (auto const& stateProbabilityPair : choice) {
transitionMatrix.insertNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
@ -1028,7 +1131,7 @@ namespace storm {
// Now add all rewards that match this choice.
for (auto const& transitionReward : transitionRewards) {
if (transitionReward.getActionName() == "" && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) {
stateToRewardMap[stateProbabilityPair.first] += transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState));
stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState)));
}
}
@ -1141,11 +1244,11 @@ namespace storm {
static std::vector<ValueType> buildStateRewards(std::vector<storm::ir::StateReward> const& rewards, StateInformation const& stateInformation) {
std::vector<ValueType> result(stateInformation.reachableStates.size());
for (uint_fast64_t index = 0; index < stateInformation.reachableStates.size(); index++) {
result[index] = 0;
result[index] = ValueType(0);
for (auto const& reward : rewards) {
// Add this reward to the state if the state is included in the state reward.
if (reward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates[index])) {
result[index] += reward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates[index]);
result[index] += ValueType(reward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates[index]));
}
}
}

2
src/ir/Command.cpp

@ -31,7 +31,7 @@ namespace storm {
}
this->updates.reserve(oldCommand.getNumberOfUpdates());
for (Update const& update : oldCommand.updates) {
this->updates.emplace_back(update, renaming, variableState);
this->updates.emplace_back(update, variableState.getNextGlobalUpdateIndex(), renaming, variableState);
}
}

12
src/ir/Update.cpp

@ -14,16 +14,16 @@
namespace storm {
namespace ir {
Update::Update() : likelihoodExpression(), booleanAssignments(), integerAssignments() {
Update::Update() : likelihoodExpression(), booleanAssignments(), integerAssignments(), globalIndex() {
// Nothing to do here.
}
Update::Update(std::shared_ptr<storm::ir::expressions::BaseExpression> const& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments)
: likelihoodExpression(likelihoodExpression), booleanAssignments(booleanAssignments), integerAssignments(integerAssignments) {
Update::Update(uint_fast64_t globalIndex, std::shared_ptr<storm::ir::expressions::BaseExpression> const& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments)
: likelihoodExpression(likelihoodExpression), booleanAssignments(booleanAssignments), integerAssignments(integerAssignments), globalIndex(globalIndex) {
// Nothing to do here.
}
Update::Update(Update const& update, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) {
Update::Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) : globalIndex(newGlobalIndex) {
for (auto const& variableAssignmentPair : update.booleanAssignments) {
if (renaming.count(variableAssignmentPair.first) > 0) {
this->booleanAssignments[renaming.at(variableAssignmentPair.first)] = Assignment(variableAssignmentPair.second, renaming, variableState);
@ -81,6 +81,10 @@ namespace storm {
return variableAssignmentPair->second;
}
uint_fast64_t Update::getGlobalIndex() const {
return this->globalIndex;
}
std::string Update::toString() const {
std::stringstream result;
result << likelihoodExpression->toString() << " : ";

20
src/ir/Update.h

@ -38,20 +38,22 @@ namespace storm {
* Creates an update with the given expression specifying the likelihood and the mapping of
* variable to their assignments.
*
* @param globalIndex The global index of the update.
* @param likelihoodExpression An expression specifying the likelihood of this update.
* @param assignments A map of variable names to their assignments.
*/
Update(std::shared_ptr<storm::ir::expressions::BaseExpression> const& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments);
Update(uint_fast64_t globalIndex, std::shared_ptr<storm::ir::expressions::BaseExpression> const& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments);
/*!
* Creates a copy of the given update and performs the provided renaming.
*
* update The update that is to be copied.
* renaming A mapping from names that are to be renamed to the names they are to be
* @param update The update that is to be copied.
* @param newGlobalIndex The global index of the resulting update.
* @param renaming A mapping from names that are to be renamed to the names they are to be
* replaced with.
* @param variableState An object knowing about the variables in the system.
*/
Update(Update const& update, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState);
Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState);
/*!
* Retrieves the expression for the likelihood of this update.
@ -102,6 +104,13 @@ namespace storm {
*/
storm::ir::Assignment const& getIntegerAssignment(std::string const& variableName) const;
/*!
* Retrieves the global index of the update, that is, a unique index over all modules.
*
* @return The global index of the update.
*/
uint_fast64_t getGlobalIndex() const;
/*!
* Retrieves a string representation of this update.
*
@ -118,6 +127,9 @@ namespace storm {
// A mapping of integer variable names to their assignments in this update.
std::map<std::string, storm::ir::Assignment> integerAssignments;
// The global index of the update.
uint_fast64_t globalIndex;
};
} // namespace ir

8
src/parser/prismparser/PrismGrammar.cpp

@ -111,8 +111,9 @@ TransitionReward createTransitionReward(std::string const& label, std::shared_pt
void createRewardModel(std::string const& name, std::vector<StateReward>& stateRewards, std::vector<TransitionReward>& transitionRewards, std::map<std::string, RewardModel>& mapping) {
mapping[name] = RewardModel(name, stateRewards, transitionRewards);
}
Update createUpdate(std::shared_ptr<BaseExpression> likelihood, std::map<std::string, Assignment> const& bools, std::map<std::string, Assignment> const& ints) {
return Update(likelihood, bools, ints);
Update PrismGrammar::createUpdate(std::shared_ptr<BaseExpression> likelihood, std::map<std::string, Assignment> const& bools, std::map<std::string, Assignment> const& ints) {
this->state->nextGlobalUpdateIndex++;
return Update(this->state->getNextGlobalUpdateIndex() - 1, likelihood, bools, ints);
}
Command PrismGrammar::createCommand(std::string const& label, std::shared_ptr<BaseExpression> guard, std::vector<Update> const& updates) {
this->state->nextGlobalCommandIndex++;
@ -166,8 +167,7 @@ PrismGrammar::PrismGrammar() : PrismGrammar::base_type(start), state(new Variabl
assignmentDefinition.name("assignment");
assignmentDefinitionList = assignmentDefinition(qi::_r1, qi::_r2) % "&";
assignmentDefinitionList.name("assignment list");
updateDefinition = (
ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(":")[phoenix::clear(phoenix::ref(this->state->assignedBooleanVariables_)), phoenix::clear(phoenix::ref(this->state->assignedIntegerVariables_))] > assignmentDefinitionList(qi::_a, qi::_b))[qi::_val = phoenix::bind(&createUpdate, qi::_1, qi::_a, qi::_b)];
updateDefinition = (ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(":")[phoenix::clear(phoenix::ref(this->state->assignedBooleanVariables_)), phoenix::clear(phoenix::ref(this->state->assignedIntegerVariables_))] > assignmentDefinitionList(qi::_a, qi::_b))[qi::_val = phoenix::bind(&PrismGrammar::createUpdate, this, qi::_1, qi::_a, qi::_b)];
updateDefinition.name("update");
updateListDefinition = +updateDefinition % "+";
updateListDefinition.name("update list");

15
src/parser/prismparser/PrismGrammar.h

@ -5,8 +5,8 @@
* Created on April 30, 2013, 5:20 PM
*/
#ifndef PRISMGRAMMAR_H
#define PRISMGRAMMAR_H
#ifndef STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H
#define STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H
// All classes of the intermediate representation are used.
#include "src/ir/IR.h"
@ -239,6 +239,15 @@ private:
*/
Command createCommand(std::string const& label, std::shared_ptr<BaseExpression> guard, std::vector<Update> const& updates);
/*!
* Creates an update with the given likelihood and the given assignments to boolean and integer variables, respectively.
*
* @param likelihood The likelihood of this update being executed.
* @param booleanAssignments The assignments to boolean variables this update involves.
* @param integerAssignments The assignments to integer variables this update involves.
*/
Update createUpdate(std::shared_ptr<BaseExpression> likelihood, std::map<std::string, Assignment> const& booleanAssignments, std::map<std::string, Assignment> const& integerAssignments);
};
@ -247,5 +256,5 @@ private:
} // namespace storm
#endif /* PRISMGRAMMAR_H */
#endif /* STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H */

7
src/parser/prismparser/VariableState.cpp

@ -31,7 +31,7 @@ std::ostream& operator<<(std::ostream& out, VariableState::variableNamesStruct&
}
VariableState::VariableState(bool firstRun) : firstRun(firstRun), keywords(), nextLocalBooleanVariableIndex(0), nextLocalIntegerVariableIndex(0), nextGlobalBooleanVariableIndex(0), nextGlobalIntegerVariableIndex(0), nextGlobalCommandIndex(0) {
VariableState::VariableState(bool firstRun) : firstRun(firstRun), keywords(), nextLocalBooleanVariableIndex(0), nextLocalIntegerVariableIndex(0), nextGlobalBooleanVariableIndex(0), nextGlobalIntegerVariableIndex(0), nextGlobalCommandIndex(0), nextGlobalUpdateIndex(0) {
// Nothing to do here.
}
@ -55,6 +55,10 @@ uint_fast64_t VariableState::getNextGlobalCommandIndex() const {
return this->nextGlobalCommandIndex;
}
uint_fast64_t VariableState::getNextGlobalUpdateIndex() const {
return this->nextGlobalUpdateIndex;
}
uint_fast64_t VariableState::addBooleanVariable(std::string const& name) {
if (firstRun) {
LOG4CPLUS_TRACE(logger, "Adding boolean variable " << name << " with new id " << this->nextGlobalBooleanVariableIndex << ".");
@ -166,6 +170,7 @@ void VariableState::prepareForSecondRun() {
allConstantNames_.clear();
this->firstRun = false;
nextGlobalCommandIndex = 0;
nextGlobalUpdateIndex = 0;
}
} // namespace prism

20
src/parser/prismparser/VariableState.h

@ -5,8 +5,8 @@
* Created on April 10, 2013, 4:43 PM
*/
#ifndef VARIABLESTATE_H
#define VARIABLESTATE_H
#ifndef STORM_PARSER_PRISMPARSER_VARIABLESTATE_H
#define STORM_PARSER_PRISMPARSER_VARIABLESTATE_H
#include <iostream>
@ -15,9 +15,7 @@
#include "Tokens.h"
namespace storm {
namespace parser {
namespace prism {
using namespace storm::ir;
@ -111,6 +109,18 @@ public:
*/
uint_fast64_t getNextGlobalCommandIndex() const;
/*!
* Internal counter for the index of the next update.
*/
uint_fast64_t nextGlobalUpdateIndex;
/*!
* Retrieves the next free global index for an update.
*
* @return The next free global index for an update.
*/
uint_fast64_t getNextGlobalUpdateIndex() const;
// Structures mapping variable and constant names to the corresponding expression nodes of
// the intermediate representation.
struct qi::symbols<char, std::shared_ptr<VariableExpression>> integerVariables_, booleanVariables_;
@ -193,5 +203,5 @@ public:
} // namespace parser
} // namespace storm
#endif /* VARIABLESTATE_H */
#endif /* STORM_PARSER_PRISMPARSER_VARIABLESTATE_H */

38
src/storage/LabeledValues.h

@ -25,7 +25,7 @@ namespace storm {
/*!
* Default-constructs an empty object.
*/
LabeledValues() : valueLabelList() {
explicit LabeledValues() : valueLabelList() {
// Intentionally left empty.
}
@ -34,7 +34,7 @@ namespace storm {
*
* @param value The probability to sto
*/
LabeledValues(ValueType value) : valueLabelList() {
explicit LabeledValues(ValueType value) : valueLabelList() {
addValue(value);
}
@ -116,9 +116,9 @@ namespace storm {
}
/*!
* Adds all labeled probabilities of the given object to the current one.
* Adds all labeled values of the given object to the current one.
*
* @param labeledProbabilities The labeled probabilities to add to the object.
* @param labeledValues The labeled values to add to the object.
*/
LabeledValues<ValueType>& operator+=(LabeledValues<ValueType> const& labeledValues) {
for (auto const& valueLabelListPair : labeledValues) {
@ -127,6 +127,36 @@ namespace storm {
return *this;
}
/*!
* Divides the values by the given value.
*
* @param value The value by which to divide.
* @return A collection of labeled values that have the same labels as the current object, but whose values
* are divided by the given one.
*/
LabeledValues<ValueType> operator/(ValueType value) const {
LabeledValues<ValueType> result;
for (auto const& valueLabelListPair : valueLabelList) {
result.addValue(valueLabelListPair.first / value, valueLabelListPair.second);
}
return result;
}
/*!
* Divides the values by the given unsigned integer value.
*
* @param value The unsigned integer value by which to divide.
* @return A collection of labeled values that have the same labels as the current object, but whose values
* are divided by the given one.
*/
LabeledValues<ValueType> operator/(uint_fast64_t value) const {
LabeledValues<ValueType> result;
for (auto const& valueLabelListPair : valueLabelList) {
result.addValue(valueLabelListPair.first / value, valueLabelListPair.second);
}
return result;
}
/*!
* Converts the object into the value type by returning the sum.
*

9
test/functional/parser/ParsePrismTest.cpp

@ -14,9 +14,7 @@ TEST(ParsePrismTest, parseCrowds5_5) {
ASSERT_TRUE(storm::settings::Settings::getInstance()->isSet("fixDeadlocks"));
storm::ir::Program program;
ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.pm"));
storm::adapters::ExplicitModelAdapter adapter(program);
std::shared_ptr<storm::models::Dtmc<double>> model = adapter.getModel()->as<storm::models::Dtmc<double>>();
std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program);
ASSERT_EQ(model->getNumberOfStates(), 8607ull);
ASSERT_EQ(model->getNumberOfTransitions(), 15113ull);
@ -25,11 +23,10 @@ TEST(ParsePrismTest, parseCrowds5_5) {
TEST(ParsePrismTest, parseTwoDice) {
storm::ir::Program program;
ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.nm"));
storm::adapters::ExplicitModelAdapter adapter(program);
std::shared_ptr<storm::models::Mdp<double>> model = adapter.getModel()->as<storm::models::Mdp<double>>();
std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program);
ASSERT_EQ(model->getNumberOfStates(), 169ull);
ASSERT_EQ(model->getNumberOfChoices(), 254ull);
ASSERT_EQ(model->as<storm::models::AbstractNondeterministicModel<double>>()->getNumberOfChoices(), 254ull);
ASSERT_EQ(model->getNumberOfTransitions(), 436ull);
}
Loading…
Cancel
Save