Browse Source

created storage class for JANI assignments that guarantees ordering

Former-commit-id: 6cc43016a2 [formerly aaa7b8a213]
Former-commit-id: 8eb1c8d54d
tempestpy_adaptions
dehnert 9 years ago
parent
commit
2182beefcb
  1. 46
      src/adapters/DereferenceIteratorAdapter.h
  2. 10
      src/generator/JaniNextStateGenerator.cpp
  3. 3
      src/generator/PrismNextStateGenerator.cpp
  4. 31
      src/storage/jani/Assignment.cpp
  5. 22
      src/storage/jani/Assignment.h
  6. 14
      src/storage/jani/Edge.cpp
  7. 23
      src/storage/jani/Edge.h
  8. 100
      src/storage/jani/EdgeDestination.cpp
  9. 61
      src/storage/jani/EdgeDestination.h
  10. 438
      src/storage/jani/Exporter.cpp
  11. 48
      src/storage/jani/Exporter.h
  12. 14
      src/storage/jani/Location.cpp
  13. 8
      src/storage/jani/Location.h
  14. 116
      src/storage/jani/OrderedAssignments.cpp
  15. 91
      src/storage/jani/OrderedAssignments.h
  16. 90
      src/storage/jani/VariableSet.cpp
  17. 72
      src/storage/jani/VariableSet.h

46
src/adapters/DereferenceIteratorAdapter.h

@ -0,0 +1,46 @@
#pragma once
#include <type_traits>
#include <boost/iterator/transform_iterator.hpp>
namespace storm {
namespace adapters {
template<typename T>
struct Dereferencer {
decltype((*std::declval<T>())) operator()(T const& t) const {
return *t;
}
};
template<typename ContainerType>
class DereferenceIteratorAdapter {
public:
typedef typename ContainerType::value_type value_type;
typedef typename std::conditional<std::is_const<ContainerType>::value, typename ContainerType::const_iterator, typename ContainerType::iterator>::type input_iterator;
typedef typename boost::transform_iterator<Dereferencer<value_type>, input_iterator> iterator;
DereferenceIteratorAdapter(input_iterator it, input_iterator ite) : it(it), ite(ite) {
// Intentionally left empty.
}
iterator begin() {
return boost::make_transform_iterator(it, Dereferencer<value_type>());
}
iterator end() {
return boost::make_transform_iterator(ite, Dereferencer<value_type>());
}
static iterator make_iterator(input_iterator it) {
return boost::make_transform_iterator(it, Dereferencer<value_type>());
}
private:
input_iterator it;
input_iterator ite;
};
}
}

10
src/generator/JaniNextStateGenerator.cpp

@ -34,22 +34,22 @@ namespace storm {
}
}
} else {
auto const& globalVariables = model.getGlobalVariables();
// Extract the reward models from the program based on the names we were given.
for (auto const& rewardModelName : this->options.getRewardModelNames()) {
auto const& globalVariables = model.getGlobalVariables();
if (globalVariables.hasVariable(rewardModelName)) {
rewardVariables.push_back(globalVariables.getVariable(rewardModelName).getExpressionVariable());
} else {
STORM_LOG_THROW(rewardModelName.empty(), storm::exceptions::InvalidArgumentException, "Cannot build unknown reward model '" << rewardModelName << "'.");
STORM_LOG_THROW(globalVariables.getNumberOfTransientVariables() == 1, storm::exceptions::InvalidArgumentException, "Reference to standard reward model is ambiguous.");
STORM_LOG_THROW(this->program.getNumberOfRewardModels() > 0, storm::exceptions::InvalidArgumentException, "Reference to standard reward model is invalid, because there is no reward model.");
}
}
// If no reward model was yet added, but there was one that was given in the options, we try to build
// If no reward model was yet added, but there was one that was given in the options, we try to build the
// standard reward model.
if (rewardModels.empty() && !this->options.getRewardModelNames().empty()) {
rewardModels.push_back(this->program.getRewardModel(0));
if (rewardVariables.empty() && !this->options.getRewardModelNames().empty()) {
rewardVariables.push_back(globalVariables.getTransientVariables().front()->getExpressionVariable());
}
}

3
src/generator/PrismNextStateGenerator.cpp

@ -42,11 +42,10 @@ namespace storm {
} else {
STORM_LOG_THROW(rewardModelName.empty(), storm::exceptions::InvalidArgumentException, "Cannot build unknown reward model '" << rewardModelName << "'.");
STORM_LOG_THROW(this->program.getNumberOfRewardModels() == 1, storm::exceptions::InvalidArgumentException, "Reference to standard reward model is ambiguous.");
STORM_LOG_THROW(this->program.getNumberOfRewardModels() > 0, storm::exceptions::InvalidArgumentException, "Reference to standard reward model is invalid, because there is no reward model.");
}
}
// If no reward model was yet added, but there was one that was given in the options, we try to build
// If no reward model was yet added, but there was one that was given in the options, we try to build the
// standard reward model.
if (rewardModels.empty() && !this->options.getRewardModelNames().empty()) {
rewardModels.push_back(this->program.getRewardModel(0));

31
src/storage/jani/Assignment.cpp

@ -1,14 +1,18 @@
#include "src/storage/jani/Assignment.h"
#include "src/utility/macros.h"
#include "src/exceptions/NotImplementedException.h"
namespace storm {
namespace jani {
Assignment::Assignment(storm::jani::Variable const& variable, storm::expressions::Expression const& expression) : variable(variable), expression(expression) {
// Intentionally left empty.
Assignment::Assignment(storm::jani::Variable const& variable, storm::expressions::Expression const& expression, uint64_t level) : variable(variable), expression(expression), level(level) {
STORM_LOG_THROW(level == 0, storm::exceptions::NotImplementedException, "Assignment levels other than 0 are currently not supported.");
}
bool Assignment::operator==(Assignment const& other) const {
return this->isTransientAssignment() == other.isTransientAssignment() && this->getExpressionVariable() == other.getExpressionVariable() && this->getAssignedExpression().isSyntacticallyEqual(other.getAssignedExpression());
// FIXME: the level is currently ignored as we do not support it
return this->isTransient() == other.isTransient() && this->getExpressionVariable() == other.getExpressionVariable() && this->getAssignedExpression().isSyntacticallyEqual(other.getAssignedExpression());
}
storm::jani::Variable const& Assignment::getVariable() const {
@ -27,7 +31,7 @@ namespace storm {
this->expression = expression;
}
bool Assignment::isTransientAssignment() const {
bool Assignment::isTransient() const {
return this->variable.get().isTransient();
}
@ -35,10 +39,29 @@ namespace storm {
this->setAssignedExpression(this->getAssignedExpression().substitute(substitution));
}
uint64_t Assignment::getLevel() const {
return level;
}
std::ostream& operator<<(std::ostream& stream, Assignment const& assignment) {
stream << assignment.getVariable().getName() << " := " << assignment.getAssignedExpression();
return stream;
}
bool AssignmentPartialOrderByVariable::operator()(Assignment const& left, Assignment const& right) const {
return left.getExpressionVariable() < right.getExpressionVariable();
}
bool AssignmentPartialOrderByVariable::operator()(Assignment const& left, std::shared_ptr<Assignment> const& right) const {
return left.getExpressionVariable() < right->getExpressionVariable();
}
bool AssignmentPartialOrderByVariable::operator()(std::shared_ptr<Assignment> const& left, std::shared_ptr<Assignment> const& right) const {
return left->getExpressionVariable() < right->getExpressionVariable();
}
bool AssignmentPartialOrderByVariable::operator()(std::shared_ptr<Assignment> const& left, Assignment const& right) const {
return left->getExpressionVariable() < right.getExpressionVariable();
}
}
}

22
src/storage/jani/Assignment.h

@ -13,7 +13,7 @@ namespace storm {
/*!
* Creates an assignment of the given expression to the given variable.
*/
Assignment(storm::jani::Variable const& variable, storm::expressions::Expression const& expression);
Assignment(storm::jani::Variable const& variable, storm::expressions::Expression const& expression, uint64_t index = 0);
bool operator==(Assignment const& other) const;
@ -45,7 +45,12 @@ namespace storm {
/**
* Retrieves whether the assignment assigns to a transient variable.
*/
bool isTransientAssignment() const;
bool isTransient() const;
/*!
* Retrieves the level of the assignment.
*/
uint64_t getLevel() const;
friend std::ostream& operator<<(std::ostream& stream, Assignment const& assignment);
@ -55,7 +60,20 @@ namespace storm {
// The expression that is being assigned to the variable.
storm::expressions::Expression expression;
// The level of the assignment.
uint64_t level;
};
/*!
* This functor enables ordering the assignments by variable. Note that this is a partial order.
*/
struct AssignmentPartialOrderByVariable {
bool operator()(Assignment const& left, Assignment const& right) const;
bool operator()(Assignment const& left, std::shared_ptr<Assignment> const& right) const;
bool operator()(std::shared_ptr<Assignment> const& left, std::shared_ptr<Assignment> const& right) const;
bool operator()(std::shared_ptr<Assignment> const& left, Assignment const& right) const;
};
}
}

14
src/storage/jani/Edge.cpp

@ -2,6 +2,9 @@
#include "src/storage/jani/Model.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm {
namespace jani {
@ -49,11 +52,7 @@ namespace storm {
destinations.push_back(destination);
}
std::vector<Assignment>& Edge::getTransientAssignments() {
return transientAssignments;
}
std::vector<Assignment> const& Edge::getTransientAssignments() const {
OrderedAssignments const& Edge::getTransientAssignments() const {
return transientAssignments;
}
@ -80,8 +79,9 @@ namespace storm {
}
}
void Edge::addTransientAssignment(Assignment const& assignment) {
transientAssignments.push_back(assignment);
bool Edge::addTransientAssignment(Assignment const& assignment) {
STORM_LOG_THROW(assignment.isTransient(), storm::exceptions::InvalidArgumentException, "Must not add non-transient assignment to location.");
return transientAssignments.add(assignment);
}
void Edge::liftTransientDestinationAssignments() {

23
src/storage/jani/Edge.h

@ -4,6 +4,7 @@
#include <boost/container/flat_set.hpp>
#include "src/storage/jani/EdgeDestination.h"
#include "src/storage/jani/OrderedAssignments.h"
namespace storm {
namespace jani {
@ -64,16 +65,6 @@ namespace storm {
*/
void addDestination(EdgeDestination const& destination);
/*!
* Retrieves the transient assignments of this edge.
*/
std::vector<Assignment>& getTransientAssignments();
/*!
* Retrieves the transient assignments of this edge.
*/
std::vector<Assignment> const& getTransientAssignments() const;
/*!
* Substitutes all variables in all expressions according to the given substitution.
*/
@ -90,14 +81,20 @@ namespace storm {
* that prior to calling this, the edge has to be finalized.
*/
boost::container::flat_set<storm::expressions::Variable> const& getWrittenGlobalVariables() const;
/*!
* Adds a transient assignment to this edge.
*
* @param assignment The transient assignment to add.
* @return True if the assignment was added.
*/
void addTransientAssignment(Assignment const& assignment);
bool addTransientAssignment(Assignment const& assignment);
/*!
* Retrieves the transient assignments of this edge.
*/
OrderedAssignments const& getTransientAssignments() const;
/*!
* Finds the transient assignments common to all destinations and lifts them to the edge. Afterwards, these
* assignments are no longer contained in the destination.
@ -122,7 +119,7 @@ namespace storm {
std::vector<EdgeDestination> destinations;
/// The transient assignments made when taking this edge.
std::vector<Assignment> transientAssignments;
OrderedAssignments transientAssignments;
/// A set of global variables that is written by at least one of the edge's destinations. This set is
/// initialized by the call to <code>finalize</code>.

100
src/storage/jani/EdgeDestination.cpp

@ -7,33 +7,11 @@ namespace storm {
namespace jani {
EdgeDestination::EdgeDestination(uint64_t locationIndex, storm::expressions::Expression const& probability, std::vector<Assignment> const& assignments) : locationIndex(locationIndex), probability(probability), assignments(assignments) {
for (auto const& assignment : assignments) {
if (assignment.isTransientAssignment()) {
transientAssignments.push_back(assignment);
} else {
nonTransientAssignments.push_back(assignment);
}
}
sortAssignments(this->assignments);
sortAssignments(transientAssignments);
sortAssignments(nonTransientAssignments);
// Intentionally left empty.
}
void EdgeDestination::addAssignment(Assignment const& assignment) {
// We make sure that there are no two assignments to the same variable.
for (auto const& oldAssignment : assignments) {
STORM_LOG_THROW(oldAssignment.getExpressionVariable() != assignment.getExpressionVariable(), storm::exceptions::WrongFormatException, "Cannot add assignment '" << assignment << "', because another assignment '" << assignment << "' writes to the same target variable.");
}
assignments.push_back(assignment);
sortAssignments(assignments);
if (assignment.isTransientAssignment()) {
transientAssignments.push_back(assignment);
sortAssignments(transientAssignments);
} else {
nonTransientAssignments.push_back(assignment);
sortAssignments(nonTransientAssignments);
}
assignments.add(assignment);
}
uint64_t EdgeDestination::getLocationIndex() const {
@ -48,84 +26,30 @@ namespace storm {
this->probability = probability;
}
std::vector<Assignment>& EdgeDestination::getAssignments() {
return assignments;
storm::jani::detail::ConstAssignments EdgeDestination::getAssignments() const {
return assignments.getAllAssignments();
}
std::vector<Assignment> const& EdgeDestination::getAssignments() const {
return assignments;
}
std::vector<Assignment>& EdgeDestination::getNonTransientAssignments() {
return nonTransientAssignments;
}
std::vector<Assignment> const& EdgeDestination::getNonTransientAssignments() const {
return nonTransientAssignments;
}
std::vector<Assignment>& EdgeDestination::getTransientAssignments() {
return transientAssignments;
storm::jani::detail::ConstAssignments EdgeDestination::getTransientAssignments() const {
return assignments.getTransientAssignments();
}
std::vector<Assignment> const& EdgeDestination::getTransientAssignments() const {
return transientAssignments;
storm::jani::detail::ConstAssignments EdgeDestination::getNonTransientAssignments() const {
return assignments.getNonTransientAssignments();
}
void EdgeDestination::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) {
this->setProbability(this->getProbability().substitute(substitution));
for (auto& assignment : this->getAssignments()) {
assignment.substitute(substitution);
}
for (auto& assignment : this->getTransientAssignments()) {
assignment.substitute(substitution);
}
for (auto& assignment : this->getNonTransientAssignments()) {
assignment.substitute(substitution);
}
assignments.substitute(substitution);
}
bool EdgeDestination::hasAssignment(Assignment const& assignment) const {
for (auto const& containedAssignment : assignments) {
if (containedAssignment == assignment) {
return true;
}
}
return false;
return assignments.contains(assignment);
}
bool EdgeDestination::removeAssignment(Assignment const& assignment) {
bool toRemove = removeAssignment(assignment, assignments);
if (toRemove) {
if (assignment.isTransientAssignment()) {
removeAssignment(assignment, transientAssignments);
} else {
removeAssignment(assignment, nonTransientAssignments);
}
return true;
}
return false;
}
void EdgeDestination::sortAssignments(std::vector<Assignment>& assignments) {
std::sort(assignments.begin(), assignments.end(), [] (storm::jani::Assignment const& assignment1, storm::jani::Assignment const& assignment2) {
bool smaller = assignment1.getExpressionVariable().getType().isBooleanType() && !assignment2.getExpressionVariable().getType().isBooleanType();
if (!smaller) {
smaller = assignment1.getExpressionVariable() < assignment2.getExpressionVariable();
}
return smaller;
});
return assignments.remove(assignment);
}
bool EdgeDestination::removeAssignment(Assignment const& assignment, std::vector<Assignment>& assignments) {
for (auto it = assignments.begin(), ite = assignments.end(); it != ite; ++it) {
if (assignment == *it) {
assignments.erase(it);
return true;
}
}
return false;
}
}
}

61
src/storage/jani/EdgeDestination.h

@ -4,7 +4,7 @@
#include "src/storage/expressions/Expression.h"
#include "src/storage/jani/Assignment.h"
#include "src/storage/jani/OrderedAssignments.h"
namespace storm {
namespace jani {
@ -39,81 +39,36 @@ namespace storm {
/*!
* Retrieves the assignments to make when choosing this destination.
*/
std::vector<Assignment>& getAssignments();
storm::jani::detail::ConstAssignments getAssignments() const;
/*!
* Retrieves the assignments to make when choosing this destination.
*/
std::vector<Assignment> const& getAssignments() const;
/*!
* Retrieves the non-transient assignments to make when choosing this destination.
*/
std::vector<Assignment>& getNonTransientAssignments();
/*!
* Retrieves the non-transient assignments to make when choosing this destination.
* Retrieves the transient assignments to make when choosing this destination.
*/
std::vector<Assignment> const& getNonTransientAssignments() const;
storm::jani::detail::ConstAssignments getTransientAssignments() const;
/*!
* Retrieves the non-transient assignments to make when choosing this destination.
*/
std::vector<Assignment>& getTransientAssignments();
/*!
* Retrieves the non-transient assignments to make when choosing this destination.
*/
std::vector<Assignment> const& getTransientAssignments() const;
storm::jani::detail::ConstAssignments getNonTransientAssignments() const;
/*!
* Substitutes all variables in all expressions according to the given substitution.
*/
void substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution);
/*!
* Retrieves whether this assignment is made when choosing this destination.
*
* @return True iff the assignment is made.
*/
// Convenience methods to access the assignments.
bool hasAssignment(Assignment const& assignment) const;
/*!
* Removes the given assignment from this destination.
*
* @return True if the assignment was found and removed.
*/
bool removeAssignment(Assignment const& assignment);
private:
/*!
* Sorts the assignments to make all assignments to boolean variables precede all others and order the
* assignments within one variable group by the expression variables.
*/
static void sortAssignments(std::vector<Assignment>& assignments);
/*!
* Removes the given assignment from the provided list of assignments if found.
*
* @return True if the assignment was removed.
*/
static bool removeAssignment(Assignment const& assignment, std::vector<Assignment>& assignments);
// The index of the destination location.
uint64_t locationIndex;
// The probability to go to the destination.
storm::expressions::Expression probability;
// The assignments to make when choosing this destination.
std::vector<Assignment> assignments;
// The assignments to make when choosing this destination.
std::vector<Assignment> nonTransientAssignments;
// The assignments to make when choosing this destination.
std::vector<Assignment> transientAssignments;
// The (ordered) assignments to make when choosing this destination.
OrderedAssignments assignments;
};
}

438
src/storage/jani/Exporter.cpp

@ -1,438 +0,0 @@
#include "src/storage/jani/Exporter.h"
#include <iostream>
namespace storm {
namespace jani {
void appendIndent(std::stringstream& out, uint64_t indent) {
for (uint64_t i = 0; i < indent; ++i) {
out << "\t";
}
}
void appendField(std::stringstream& out, std::string const& name) {
out << "\"" << name << "\": ";
}
void appendValue(std::stringstream& out, std::string const& value) {
out << "\"" << value << "\"";
}
void clearLine(std::stringstream& out) {
out << std::endl;
}
std::string expressionToString(storm::expressions::Expression const& expression) {
std::stringstream s;
s << expression;
return s.str();
}
void Exporter::appendVersion(std::stringstream& out, uint64_t janiVersion, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "jani-version");
}
void Exporter::appendModelName(std::stringstream& out, std::string const& name, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "name");
appendValue(out, name);
}
void Exporter::appendModelType(std::stringstream& out, storm::jani::ModelType const& modelType, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "type");
}
void Exporter::appendAction(std::stringstream& out, storm::jani::Action const& action, uint64_t indent) const {
appendIndent(out, indent);
out << "{" << std::endl;
appendIndent(out, indent + 1);
appendField(out, "name");
appendValue(out, action.getName());
clearLine(out);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendActions(std::stringstream& out, storm::jani::Model const& model, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "actions");
out << " [" << std::endl;
for (uint64_t index = 0; index < model.actions.size(); ++index) {
appendAction(out, model.actions[index], indent + 1);
if (index < model.actions.size() - 1) {
out << ",";
}
clearLine(out);
}
appendIndent(out, indent);
out << "]";
}
void Exporter::appendVariable(std::stringstream& out, storm::jani::BooleanVariable const& variable, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "name");
appendValue(out, variable.getName());
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "type");
appendValue(out, "bool");
out << ",";
clearLine(out);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendBoundedIntegerVariableType(std::stringstream& out, storm::jani::BoundedIntegerVariable const& variable, uint64_t indent) const {
out << " {";
clearLine(out);
appendIndent(out, indent);
appendField(out, "kind");
appendValue(out, "bounded");
clearLine(out);
appendIndent(out, indent);
appendField(out, "base");
appendValue(out, "int");
clearLine(out);
appendIndent(out, indent);
appendField(out, "lower-bound");
appendValue(out, expressionToString(variable.getLowerBound()));
clearLine(out);
appendIndent(out, indent);
appendField(out, "upper-bound");
appendValue(out, expressionToString(variable.getLowerBound()));
clearLine(out);
appendIndent(out, indent - 1);
out << "}";
}
void Exporter::appendVariable(std::stringstream& out, storm::jani::BoundedIntegerVariable const& variable, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "name");
appendValue(out, variable.getName());
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "type");
appendBoundedIntegerVariableType(out, variable, indent + 2);
out << ",";
clearLine(out);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendVariable(std::stringstream& out, storm::jani::UnboundedIntegerVariable const& variable, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "name");
appendValue(out, variable.getName());
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "type");
appendValue(out, "int");
out << ",";
clearLine(out);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendVariables(std::stringstream& out, storm::jani::VariableSet const& variables, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "variables");
out << " [";
clearLine(out);
for (auto const& variable : variables.getBooleanVariables()) {
appendVariable(out, variable, indent + 1);
clearLine(out);
}
for (auto const& variable : variables.getBoundedIntegerVariables()) {
appendVariable(out, variable, indent + 1);
clearLine(out);
}
for (auto const& variable : variables.getUnboundedIntegerVariables()) {
appendVariable(out, variable, indent + 1);
clearLine(out);
}
appendIndent(out, indent);
out << "]";
}
void Exporter::appendLocation(std::stringstream& out, storm::jani::Location const& location, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "name");
appendValue(out, location.getName());
clearLine(out);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendLocations(std::stringstream& out, storm::jani::Automaton const& automaton, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "locations");
out << " [";
clearLine(out);
for (auto const& location : automaton.getLocations()) {
appendLocation(out, location, indent + 1);
out << ",";
clearLine(out);
}
appendIndent(out, indent);
out << "]";
}
void Exporter::appendAssignment(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, storm::jani::Assignment const& assignment, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "ref");
storm::jani::Variable const& variable = model.getGlobalVariables().hasVariable(assignment.getExpressionVariable()) ? model.getGlobalVariables().getVariable(assignment.getExpressionVariable()) : automaton.getVariables().getVariable(assignment.getExpressionVariable());
appendValue(out, variable.getName());
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "value");
appendValue(out, expressionToString(assignment.getAssignedExpression()));
clearLine(out);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendEdgeDestination(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, storm::jani::EdgeDestination const& destination, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "probability");
appendValue(out, expressionToString(destination.getProbability()));
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "location");
appendValue(out, automaton.getLocation(destination.getLocationIndex()).getName());
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "assignments");
out << " [";
clearLine(out);
for (uint64_t index = 0; index < destination.getAssignments().size(); ++index) {
appendAssignment(out, model, automaton, destination.getAssignments()[index], indent + 2);
if (index < destination.getAssignments().size() - 1) {
out << ",";
}
clearLine(out);
}
appendIndent(out, indent + 1);
out << "]";
clearLine(out);
appendIndent(out, indent);
out << "}";
clearLine(out);
}
void Exporter::appendEdge(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, storm::jani::Edge const& edge, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "location");
appendValue(out, automaton.getLocation(edge.getSourceLocationIndex()).getName());
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "action");
appendValue(out, model.getAction(edge.getActionIndex()).getName());
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "guard");
appendValue(out, expressionToString(edge.getGuard()));
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "destinations");
out << " [";
clearLine(out);
for (auto const& destination : edge.getDestinations()) {
appendEdgeDestination(out, model, automaton, destination, indent + 2);
}
appendIndent(out, indent + 1);
out << "]";
clearLine(out);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendEdges(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "edges");
out << " [";
clearLine(out);
for (uint64_t location = 0; location < automaton.getNumberOfLocations(); ++location) {
for (auto const& edge : automaton.getEdgesFromLocation(location)) {
appendEdge(out, model, automaton, edge, indent + 1);
out << ",";
clearLine(out);
}
}
appendIndent(out, indent);
out << "]";
clearLine(out);
}
void Exporter::appendAutomaton(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, uint64_t indent) const {
appendIndent(out, indent);
out << "{";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "name");
appendValue(out, automaton.getName());
clearLine(out);
appendVariables(out, automaton.getVariables(), indent + 1);
out << ",";
clearLine(out);
appendLocations(out, automaton, indent + 1);
out << ",";
clearLine(out);
appendIndent(out, indent + 1);
appendField(out, "initial-locations");
out << " [";
clearLine(out);
for (auto const& index : automaton.getInitialLocationIndices()) {
appendIndent(out, indent + 2);
appendValue(out, automaton.getLocation(index).getName());
clearLine(out);
}
appendIndent(out, indent + 1);
out << "]";
clearLine(out);
if (automaton.hasInitialStatesRestriction()) {
appendIndent(out, indent + 1);
appendField(out, "initial-states");
clearLine(out);
appendIndent(out, indent + 2);
out << "{";
clearLine(out);
appendIndent(out, indent + 3);
appendField(out, "exp");
appendValue(out, expressionToString(automaton.getInitialStatesExpression()));
clearLine(out);
appendIndent(out, indent + 2);
out << "}";
clearLine(out);
}
appendEdges(out, model, automaton, indent + 1);
appendIndent(out, indent);
out << "}";
}
void Exporter::appendAutomata(std::stringstream& out, storm::jani::Model const& model, uint64_t indent) const {
appendIndent(out, indent);
appendField(out, "automata");
out << " [";
clearLine(out);
for (uint64_t index = 0; index < model.automata.size(); ++index) {
appendAutomaton(out, model, model.automata[index], indent + 1);
if (index < model.automata.size() - 1) {
out << ",";
}
clearLine(out);
}
appendIndent(out, indent);
out << "]";
}
std::string Exporter::toJaniString(storm::jani::Model const& model) const {
std::stringstream out;
out << "{" << std::endl;
appendVersion(out, model.getJaniVersion(), 1);
out << ",";
clearLine(out);
appendModelName(out, model.getName(), 1);
out << ",";
clearLine(out);
appendModelType(out, model.getModelType(), 1);
out << ",";
clearLine(out);
appendActions(out, model, 1);
clearLine(out);
appendVariables(out, model.getGlobalVariables(), 1);
clearLine(out);
appendIndent(out, 1);
appendField(out, "initial-states");
clearLine(out);
appendIndent(out, 2);
out << "{";
clearLine(out);
appendIndent(out, 3);
appendField(out, "exp");
appendValue(out, expressionToString(model.getInitialStatesRestriction()));
clearLine(out);
appendIndent(out, 2);
out << "}";
clearLine(out);
appendAutomata(out, model, 1);
clearLine(out);
out << "}" << std::endl;
return out.str();
}
}
}

48
src/storage/jani/Exporter.h

@ -1,48 +0,0 @@
#pragma once
#include <sstream>
#include <cstdint>
#include "src/storage/jani/Model.h"
namespace storm {
namespace jani {
class Exporter {
public:
Exporter() = default;
std::string toJaniString(storm::jani::Model const& model) const;
private:
void appendVersion(std::stringstream& out, uint64_t janiVersion, uint64_t indent) const;
void appendModelName(std::stringstream& out, std::string const& name, uint64_t indent) const;
void appendModelType(std::stringstream& out, storm::jani::ModelType const& modelType, uint64_t indent) const;
void appendAction(std::stringstream& out, storm::jani::Action const& action, uint64_t indent) const;
void appendActions(std::stringstream& out, storm::jani::Model const& model, uint64_t indent) const;
void appendVariables(std::stringstream& out, storm::jani::VariableSet const& variables, uint64_t indent) const;
void appendVariable(std::stringstream& out, storm::jani::BooleanVariable const& variable, uint64_t indent) const;
void appendVariable(std::stringstream& out, storm::jani::BoundedIntegerVariable const& variable, uint64_t indent) const;
void appendBoundedIntegerVariableType(std::stringstream& out, storm::jani::BoundedIntegerVariable const& variable, uint64_t indent) const;
void appendVariable(std::stringstream& out, storm::jani::UnboundedIntegerVariable const& variable, uint64_t indent) const;
void appendAutomata(std::stringstream& out, storm::jani::Model const& model, uint64_t indent) const;
void appendAutomaton(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, uint64_t indent) const;
void appendLocation(std::stringstream& out, storm::jani::Location const& location, uint64_t indent) const;
void appendLocations(std::stringstream& out, storm::jani::Automaton const& automaton, uint64_t indent) const;
void appendAssignment(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, storm::jani::Assignment const& assignment, uint64_t indent) const;
void appendEdgeDestination(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, storm::jani::EdgeDestination const& destination, uint64_t indent) const;
void appendEdge(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, storm::jani::Edge const& edge, uint64_t indent) const;
void appendEdges(std::stringstream& out, storm::jani::Model const& model, storm::jani::Automaton const& automaton, uint64_t indent) const;
};
}
}

14
src/storage/jani/Location.cpp

@ -1,7 +1,8 @@
#include "src/storage/jani/Location.h"
#include "src/storage/jani/Assignment.h"
#include "src/exceptions/InvalidJaniException.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidJaniException.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm {
namespace jani {
@ -14,18 +15,17 @@ namespace storm {
return name;
}
std::vector<Assignment> const& Location::getTransientAssignments() const {
OrderedAssignments const& Location::getTransientAssignments() const {
return transientAssignments;
}
void Location::addTransientAssignment(storm::jani::Assignment const& assignment) {
transientAssignments.push_back(assignment);
STORM_LOG_THROW(assignment.isTransient(), storm::exceptions::InvalidArgumentException, "Must not add non-transient assignment to location.");
transientAssignments.add(assignment);
}
void Location::checkValid() const {
for(auto const& assignment : transientAssignments) {
STORM_LOG_THROW(assignment.isTransientAssignment(), storm::exceptions::InvalidJaniException, "Only transient assignments are allowed in locations.");
}
// Intentionally left empty.
}
}

8
src/storage/jani/Location.h

@ -1,8 +1,8 @@
#pragma once
#include <string>
#include <vector>
#include "src/storage/jani/Assignment.h"
#include "src/storage/jani/OrderedAssignments.h"
namespace storm {
namespace jani {
@ -27,7 +27,7 @@ namespace storm {
/*!
* Retrieves the transient assignments of this location.
*/
std::vector<Assignment> const& getTransientAssignments() const;
OrderedAssignments const& getTransientAssignments() const;
/*!
* Adds the given transient assignment to this location.
@ -44,7 +44,7 @@ namespace storm {
std::string name;
/// The transient assignments made in this location.
std::vector<Assignment> transientAssignments;
OrderedAssignments transientAssignments;
};
}

116
src/storage/jani/OrderedAssignments.cpp

@ -0,0 +1,116 @@
#include "src/storage/jani/OrderedAssignments.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm {
namespace jani {
OrderedAssignments::OrderedAssignments(std::vector<Assignment> const& assignments) {
for (auto const& assignment : assignments) {
add(assignment);
}
}
bool OrderedAssignments::add(Assignment const& assignment) {
// If the element is contained in this set of assignment, nothing needs to be added.
if (this->contains(assignment)) {
return false;
}
// Otherwise, we find the spot to insert it.
auto it = lowerBound(assignment, allAssignments);
if (it != allAssignments.end()) {
STORM_LOG_THROW(assignment.getExpressionVariable() != (*it)->getExpressionVariable(), storm::exceptions::InvalidArgumentException, "Cannot add assignment as an assignment to this variable already exists.");
}
// Finally, insert the new element in the correct vectors.
auto elementToInsert = std::make_shared<Assignment>(assignment);
allAssignments.emplace(it, elementToInsert);
if (assignment.isTransient()) {
auto transientIt = lowerBound(assignment, transientAssignments);
transientAssignments.emplace(transientIt, elementToInsert);
} else {
auto nonTransientIt = lowerBound(assignment, nonTransientAssignments);
nonTransientAssignments.emplace(nonTransientIt, elementToInsert);
}
return true;
}
bool OrderedAssignments::remove(Assignment const& assignment) {
// If the element is contained in this set of assignment, nothing needs to be removed.
if (!this->contains(assignment)) {
return false;
}
// Otherwise, we find the element to delete.
auto it = lowerBound(assignment, allAssignments);
STORM_LOG_ASSERT(it != allAssignments.end(), "Invalid iterator, expected existing element.");
STORM_LOG_ASSERT(assignment == **it, "Wrong iterator position.");
allAssignments.erase(it);
if (assignment.isTransient()) {
auto transientIt = lowerBound(assignment, transientAssignments);
STORM_LOG_ASSERT(transientIt != transientAssignments.end(), "Invalid iterator, expected existing element.");
STORM_LOG_ASSERT(assignment == **transientIt, "Wrong iterator position.");
transientAssignments.erase(transientIt);
} else {
auto nonTransientIt = lowerBound(assignment, nonTransientAssignments);
STORM_LOG_ASSERT(nonTransientIt != nonTransientAssignments.end(), "Invalid iterator, expected existing element.");
STORM_LOG_ASSERT(assignment == **nonTransientIt, "Wrong iterator position.");
nonTransientAssignments.erase(nonTransientIt);
}
return true;
}
bool OrderedAssignments::contains(Assignment const& assignment) const {
auto it = lowerBound(assignment, allAssignments);
if (it != allAssignments.end() && assignment == **it) {
return true;
} else {
return false;
}
}
detail::ConstAssignments OrderedAssignments::getAllAssignments() const {
return detail::ConstAssignments(allAssignments.begin(), allAssignments.end());
}
detail::ConstAssignments OrderedAssignments::getTransientAssignments() const {
return detail::ConstAssignments(transientAssignments.begin(), transientAssignments.end());
}
detail::ConstAssignments OrderedAssignments::getNonTransientAssignments() const {
return detail::ConstAssignments(nonTransientAssignments.begin(), nonTransientAssignments.end());
}
detail::Assignments::iterator OrderedAssignments::begin() {
return detail::Assignments::make_iterator(allAssignments.begin());
}
detail::ConstAssignments::iterator OrderedAssignments::begin() const {
return detail::ConstAssignments::make_iterator(allAssignments.begin());
}
detail::Assignments::iterator OrderedAssignments::end() {
return detail::Assignments::make_iterator(allAssignments.end());
}
detail::ConstAssignments::iterator OrderedAssignments::end() const {
return detail::ConstAssignments::make_iterator(allAssignments.end());
}
void OrderedAssignments::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) {
for (auto& assignment : allAssignments) {
assignment->substitute(substitution);
}
}
std::vector<std::shared_ptr<Assignment>>::const_iterator OrderedAssignments::lowerBound(Assignment const& assignment, std::vector<std::shared_ptr<Assignment>> const& assignments) {
return std::lower_bound(assignments.begin(), assignments.end(), assignment, storm::jani::AssignmentPartialOrderByVariable());
}
}
}

91
src/storage/jani/OrderedAssignments.h

@ -0,0 +1,91 @@
#pragma once
#include "src/adapters/DereferenceIteratorAdapter.h"
#include "src/storage/jani/Assignment.h"
namespace storm {
namespace jani {
namespace detail {
using Assignments = storm::adapters::DereferenceIteratorAdapter<std::vector<std::shared_ptr<Assignment>>>;
using ConstAssignments = storm::adapters::DereferenceIteratorAdapter<std::vector<std::shared_ptr<Assignment>> const>;
}
class OrderedAssignments {
public:
/*!
* Creates an ordered set of assignments.
*/
OrderedAssignments(std::vector<Assignment> const& assignments = std::vector<Assignment>());
/*!
* Adds the given assignment to the set of assignments.
*
* @return True iff the assignment was added.
*/
bool add(Assignment const& assignment);
/*!
* Removes the given assignment from this set of assignments.
*
* @return True if the assignment was found and removed.
*/
bool remove(Assignment const& assignment);
/*!
* Retrieves whether the given assignment is contained in this set of assignments.
*/
bool contains(Assignment const& assignment) const;
/*!
* Returns all assignments in this set of assignments.
*/
detail::ConstAssignments getAllAssignments() const;
/*!
* Returns all transient assignments in this set of assignments.
*/
detail::ConstAssignments getTransientAssignments() const;
/*!
* Returns all non-transient assignments in this set of assignments.
*/
detail::ConstAssignments getNonTransientAssignments() const;
/*!
* Returns an iterator to the assignments.
*/
detail::Assignments::iterator begin();
/*!
* Returns an iterator to the assignments.
*/
detail::ConstAssignments::iterator begin() const;
/*!
* Returns an iterator past the end of the assignments.
*/
detail::Assignments::iterator end();
/*!
* Returns an iterator past the end of the assignments.
*/
detail::ConstAssignments::iterator end() const;
/*!
* Substitutes all variables in all expressions according to the given substitution.
*/
void substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution);
private:
static std::vector<std::shared_ptr<Assignment>>::const_iterator lowerBound(Assignment const& assignment, std::vector<std::shared_ptr<Assignment>> const& assignments);
// The vectors to store the assignments. These need to be ordered at all times.
std::vector<std::shared_ptr<Assignment>> allAssignments;
std::vector<std::shared_ptr<Assignment>> transientAssignments;
std::vector<std::shared_ptr<Assignment>> nonTransientAssignments;
};
}
}

90
src/storage/jani/VariableSet.cpp

@ -6,46 +6,7 @@
namespace storm {
namespace jani {
namespace detail {
template<typename VariableType>
VariableType& Dereferencer<VariableType>::operator()(std::shared_ptr<VariableType> const& d) const {
return *d;
}
template<typename VariableType>
Variables<VariableType>::Variables(input_iterator it, input_iterator ite) : it(it), ite(ite) {
// Intentionally left empty.
}
template<typename VariableType>
typename Variables<VariableType>::iterator Variables<VariableType>::begin() {
return boost::make_transform_iterator(it, Dereferencer<VariableType>());
}
template<typename VariableType>
typename Variables<VariableType>::iterator Variables<VariableType>::end() {
return boost::make_transform_iterator(ite, Dereferencer<VariableType>());
}
template<typename VariableType>
ConstVariables<VariableType>::ConstVariables(const_input_iterator it, const_input_iterator ite) : it(it), ite(ite) {
// Intentionally left empty.
}
template<typename VariableType>
typename ConstVariables<VariableType>::const_iterator ConstVariables<VariableType>::begin() {
return boost::make_transform_iterator(it, Dereferencer<VariableType const>());
}
template<typename VariableType>
typename ConstVariables<VariableType>::const_iterator ConstVariables<VariableType>::end() {
return boost::make_transform_iterator(ite, Dereferencer<VariableType const>());
}
}
VariableSet::VariableSet() {
// Intentionally left empty.
}
@ -132,20 +93,20 @@ namespace storm {
return getVariable(it->second);
}
VariableSet::iterator VariableSet::begin() {
return boost::make_transform_iterator(variables.begin(), detail::Dereferencer<Variable>());
typename detail::Variables<Variable>::iterator VariableSet::begin() {
return detail::Variables<Variable>::make_iterator(variables.begin());
}
VariableSet::const_iterator VariableSet::begin() const {
return boost::make_transform_iterator(variables.begin(), detail::Dereferencer<Variable const>());
typename detail::ConstVariables<Variable>::iterator VariableSet::begin() const {
return detail::ConstVariables<Variable>::make_iterator(variables.begin());
}
VariableSet::iterator VariableSet::end() {
return boost::make_transform_iterator(variables.end(), detail::Dereferencer<Variable>());
typename detail::Variables<Variable>::iterator VariableSet::end() {
return detail::Variables<Variable>::make_iterator(variables.end());
}
VariableSet::const_iterator VariableSet::end() const {
return boost::make_transform_iterator(variables.end(), detail::Dereferencer<Variable const>());
detail::ConstVariables<Variable>::iterator VariableSet::end() const {
return detail::ConstVariables<Variable>::make_iterator(variables.end());
}
Variable const& VariableSet::getVariable(storm::expressions::Variable const& variable) const {
@ -197,20 +158,25 @@ namespace storm {
return !(containsBooleanVariable() || containsBoundedIntegerVariable() || containsUnboundedIntegerVariables());
}
template class detail::Dereferencer<Variable>;
template class detail::Dereferencer<BooleanVariable>;
template class detail::Dereferencer<BoundedIntegerVariable>;
template class detail::Dereferencer<UnboundedIntegerVariable>;
template class detail::Dereferencer<Variable const>;
template class detail::Dereferencer<BooleanVariable const>;
template class detail::Dereferencer<BoundedIntegerVariable const>;
template class detail::Dereferencer<UnboundedIntegerVariable const>;
template class detail::Variables<BooleanVariable>;
template class detail::Variables<BoundedIntegerVariable>;
template class detail::Variables<UnboundedIntegerVariable>;
template class detail::ConstVariables<BooleanVariable>;
template class detail::ConstVariables<BoundedIntegerVariable>;
template class detail::ConstVariables<UnboundedIntegerVariable>;
uint_fast64_t VariableSet::getNumberOfTransientVariables() const {
uint_fast64_t result = 0;
for (auto const& variable : variables) {
if (variable->isTransient()) {
++result;
}
}
return result;
}
std::vector<std::shared_ptr<Variable const>> VariableSet::getTransientVariables() const {
std::vector<std::shared_ptr<Variable const>> result;
for (auto const& variable : variables) {
if (variable->isTransient()) {
result.push_back(variable);
}
}
return result;
}
}
}

72
src/storage/jani/VariableSet.h

@ -3,7 +3,7 @@
#include <vector>
#include <set>
#include <boost/iterator/transform_iterator.hpp>
#include "src/adapters/DereferenceIteratorAdapter.h"
#include "src/storage/jani/BooleanVariable.h"
#include "src/storage/jani/UnboundedIntegerVariable.h"
@ -12,57 +12,17 @@
namespace storm {
namespace jani {
class VariableSet;
namespace detail {
template<typename VariableType>
class Dereferencer {
public:
VariableType& operator()(std::shared_ptr<VariableType> const& d) const;
};
template<typename VariableType>
class Variables {
public:
typedef typename std::vector<std::shared_ptr<VariableType>>::iterator input_iterator;
typedef boost::transform_iterator<Dereferencer<VariableType>, input_iterator> iterator;
Variables(input_iterator it, input_iterator ite);
iterator begin();
iterator end();
private:
input_iterator it;
input_iterator ite;
};
template<typename VariableType>
class ConstVariables {
public:
typedef typename std::vector<std::shared_ptr<VariableType>>::const_iterator const_input_iterator;
typedef boost::transform_iterator<Dereferencer<VariableType const>, const_input_iterator> const_iterator;
ConstVariables(const_input_iterator it, const_input_iterator ite);
const_iterator begin();
const_iterator end();
private:
const_input_iterator it;
const_input_iterator ite;
};
namespace detail {
template <typename VariableType>
using Variables = storm::adapters::DereferenceIteratorAdapter<std::vector<std::shared_ptr<VariableType>>>;
template <typename VariableType>
using ConstVariables = storm::adapters::DereferenceIteratorAdapter<std::vector<std::shared_ptr<VariableType>> const>;
}
class VariableSet {
public:
typedef typename std::vector<std::shared_ptr<Variable>>::iterator input_iterator;
typedef typename std::vector<std::shared_ptr<Variable>>::const_iterator const_input_iterator;
typedef boost::transform_iterator<detail::Dereferencer<Variable>, input_iterator> iterator;
typedef boost::transform_iterator<detail::Dereferencer<Variable const>, const_input_iterator> const_iterator;
/*!
* Creates an empty variable set.
*/
@ -156,22 +116,22 @@ namespace storm {
/*!
* Retrieves an iterator to the variables in this set.
*/
iterator begin();
typename detail::Variables<Variable>::iterator begin();
/*!
* Retrieves an iterator to the variables in this set.
*/
const_iterator begin() const;
typename detail::ConstVariables<Variable>::iterator begin() const;
/*!
* Retrieves the end iterator to the variables in this set.
*/
iterator end();
typename detail::Variables<Variable>::iterator end();
/*!
* Retrieves the end iterator to the variables in this set.
*/
const_iterator end() const;
typename detail::ConstVariables<Variable>::iterator end() const;
/*!
* Retrieves whether the set of variables contains a boolean variable.
@ -203,6 +163,16 @@ namespace storm {
*/
bool empty() const;
/*!
* Retrieves the number of transient variables in this variable set.
*/
uint_fast64_t getNumberOfTransientVariables() const;
/*!
* Retrieves a vector of transient variables in this variable set.
*/
std::vector<std::shared_ptr<Variable const>> getTransientVariables() const;
private:
/// The vector of all variables.
std::vector<std::shared_ptr<Variable>> variables;

Loading…
Cancel
Save