Browse Source

Merge remote-tracking branch 'origin/future' into jani_support

Former-commit-id: 2c2c57e103 [formerly 8d725b4d90]
Former-commit-id: 918275a8c7
main
dehnert 9 years ago
parent
commit
71f99eb075
  1. 2
      resources/3rdparty/CMakeLists.txt
  2. 4
      src/adapters/AddExpressionAdapter.cpp
  3. 2
      src/adapters/AddExpressionAdapter.h
  4. 4
      src/adapters/MathsatExpressionAdapter.h
  5. 4
      src/adapters/Z3ExpressionAdapter.cpp
  6. 2
      src/adapters/Z3ExpressionAdapter.h
  7. 2
      src/builder/DdPrismModelBuilder.cpp
  8. 2
      src/counterexamples/SMTMinimalCommandSetGenerator.h
  9. 3
      src/generator/JaniNextStateGenerator.cpp
  10. 11
      src/generator/PrismNextStateGenerator.cpp
  11. 1
      src/modelchecker/AbstractModelChecker.cpp
  12. 32
      src/parser/ExpressionParser.cpp
  13. 16
      src/parser/ExpressionParser.h
  14. 3
      src/parser/JaniParser.h
  15. 20
      src/parser/PrismParser.cpp
  16. 6
      src/parser/PrismParser.h
  17. 5
      src/settings/modules/CoreSettings.cpp
  18. 1
      src/settings/modules/CoreSettings.h
  19. 4
      src/storage/expressions/BinaryNumericalFunctionExpression.cpp
  20. 39
      src/storage/expressions/DoubleLiteralExpression.cpp
  21. 53
      src/storage/expressions/DoubleLiteralExpression.h
  22. 6
      src/storage/expressions/ExpressionManager.cpp
  23. 9
      src/storage/expressions/ExpressionManager.h
  24. 4
      src/storage/expressions/ExpressionVisitor.h
  25. 2
      src/storage/expressions/Expressions.h
  26. 4
      src/storage/expressions/LinearCoefficientVisitor.cpp
  27. 2
      src/storage/expressions/LinearCoefficientVisitor.h
  28. 2
      src/storage/expressions/LinearityCheckVisitor.cpp
  29. 2
      src/storage/expressions/LinearityCheckVisitor.h
  30. 53
      src/storage/expressions/RationalLiteralExpression.cpp
  31. 78
      src/storage/expressions/RationalLiteralExpression.h
  32. 2
      src/storage/expressions/SubstitutionVisitor.cpp
  33. 2
      src/storage/expressions/SubstitutionVisitor.h
  34. 2
      src/storage/expressions/ToExprtkStringVisitor.cpp
  35. 2
      src/storage/expressions/ToExprtkStringVisitor.h
  36. 11
      src/storage/expressions/ToRationalFunctionVisitor.cpp
  37. 2
      src/storage/expressions/ToRationalFunctionVisitor.h
  38. 31
      src/storage/expressions/ToRationalNumberVisitor.cpp
  39. 2
      src/storage/expressions/ToRationalNumberVisitor.h
  40. 4
      src/storage/expressions/UnaryNumericalFunctionExpression.cpp
  41. 9
      src/storage/jani/BooleanVariable.cpp
  42. 5
      src/storage/jani/BooleanVariable.h
  43. 6
      src/storage/jani/BoundedIntegerVariable.cpp
  44. 2
      src/storage/jani/BoundedIntegerVariable.h
  45. 1
      src/storage/jani/UnboundedIntegerVariable.h
  46. 16
      src/storage/prism/BooleanVariable.cpp
  47. 2
      src/storage/prism/BooleanVariable.h
  48. 7
      src/storage/prism/Constant.cpp
  49. 14
      src/storage/prism/IntegerVariable.cpp
  50. 2
      src/storage/prism/IntegerVariable.h
  51. 20
      src/storage/prism/Module.cpp
  52. 6
      src/storage/prism/Module.h
  53. 379
      src/storage/prism/Program.cpp
  54. 36
      src/storage/prism/Program.h
  55. 18
      src/storage/prism/RewardModel.cpp
  56. 9
      src/storage/prism/RewardModel.h
  57. 12
      src/storage/prism/Variable.cpp
  58. 27
      src/storage/prism/Variable.h
  59. 13
      src/storm.cpp
  60. 72
      src/utility/constants.cpp
  61. 3
      src/utility/constants.h
  62. 2
      src/utility/storm.cpp
  63. 4
      src/utility/storm.h
  64. 4
      test/functional/parser/PrismParserTest.cpp
  65. 10
      util/osx-package/package.sh
  66. 103
      util/osx-package/packager.py

2
resources/3rdparty/CMakeLists.txt

@ -204,7 +204,7 @@ if(USE_CARL)
LOG_INSTALL ON
)
add_dependencies(resources xercesc)
add_dependencies(resources carl)
include_directories(${STORM_3RDPARTY_BINARY_DIR}/carl/include)
list(APPEND STORM_LINK_LIBRARIES ${STORM_3RDPARTY_BINARY_DIR}/carl/lib/libcarl${DYNAMIC_EXT})
set(STORM_HAVE_CARL ON)

4
src/adapters/AddExpressionAdapter.cpp

@ -194,8 +194,8 @@ namespace storm {
}
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::DoubleLiteralExpression const& expression) {
return ddManager->getConstant(static_cast<ValueType>(expression.getValue()));
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::RationalLiteralExpression const& expression) {
return ddManager->getConstant(static_cast<ValueType>(expression.getValueAsDouble()));
}
// Explicitly instantiate the symbolic expression adapter

2
src/adapters/AddExpressionAdapter.h

@ -31,7 +31,7 @@ namespace storm {
virtual boost::any visit(storm::expressions::UnaryNumericalFunctionExpression const& expression) override;
virtual boost::any visit(storm::expressions::BooleanLiteralExpression const& expression) override;
virtual boost::any visit(storm::expressions::IntegerLiteralExpression const& expression) override;
virtual boost::any visit(storm::expressions::DoubleLiteralExpression const& expression) override;
virtual boost::any visit(storm::expressions::RationalLiteralExpression const& expression) override;
private:
// The manager responsible for the DDs built by this adapter.

4
src/adapters/MathsatExpressionAdapter.h

@ -171,8 +171,8 @@ namespace storm {
return expression.getValue() ? msat_make_true(env) : msat_make_false(env);
}
virtual boost::any visit(expressions::DoubleLiteralExpression const& expression) override {
return msat_make_number(env, std::to_string(expression.getValue()).c_str());
virtual boost::any visit(expressions::RationalLiteralExpression const& expression) override {
return msat_make_number(env, std::to_string(expression.getValueAsDouble()).c_str());
}
virtual boost::any visit(expressions::IntegerLiteralExpression const& expression) override {

4
src/adapters/Z3ExpressionAdapter.cpp

@ -177,6 +177,8 @@ namespace storm {
return ite(leftResult <= rightResult, leftResult, rightResult);
case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Max:
return ite(leftResult >= rightResult, leftResult, rightResult);
case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Power:
return pw(leftResult,rightResult);
default:
STORM_LOG_THROW(false, storm::exceptions::ExpressionEvaluationException, "Cannot evaluate expression: unknown numerical binary operator '" << static_cast<int>(expression.getOperatorType()) << "' in expression " << expression << ".");
}
@ -208,7 +210,7 @@ namespace storm {
return context.bool_val(expression.getValue());
}
boost::any Z3ExpressionAdapter::visit(storm::expressions::DoubleLiteralExpression const& expression) {
boost::any Z3ExpressionAdapter::visit(storm::expressions::RationalLiteralExpression const& expression) {
std::stringstream fractionStream;
fractionStream << expression.getValue();
return context.real_val(fractionStream.str().c_str());

2
src/adapters/Z3ExpressionAdapter.h

@ -63,7 +63,7 @@ namespace storm {
virtual boost::any visit(storm::expressions::BooleanLiteralExpression const& expression) override;
virtual boost::any visit(storm::expressions::DoubleLiteralExpression const& expression) override;
virtual boost::any visit(storm::expressions::RationalLiteralExpression const& expression) override;
virtual boost::any visit(storm::expressions::IntegerLiteralExpression const& expression) override;

2
src/builder/DdPrismModelBuilder.cpp

@ -1415,7 +1415,7 @@ namespace storm {
template <storm::dd::DdType Type, typename ValueType>
storm::dd::Bdd<Type> DdPrismModelBuilder<Type, ValueType>::createInitialStatesDecisionDiagram(GenerationInformation& generationInfo) {
storm::dd::Bdd<Type> initialStates = generationInfo.rowExpressionAdapter->translateExpression(generationInfo.program.getInitialConstruct().getInitialStatesExpression()).toBdd();
storm::dd::Bdd<Type> initialStates = generationInfo.rowExpressionAdapter->translateExpression(generationInfo.program.getInitialStatesExpression()).toBdd();
for (auto const& metaVariable : generationInfo.rowMetaVariables) {
initialStates &= generationInfo.manager->getRange(metaVariable);

2
src/counterexamples/SMTMinimalCommandSetGenerator.h

@ -628,7 +628,7 @@ namespace storm {
}
// Construct an expression that exactly characterizes the initial state.
storm::expressions::Expression initialStateExpression = program.getInitialConstruct().getInitialStatesExpression();
storm::expressions::Expression initialStateExpression = program.getInitialStatesExpression();
// Store the found implications in a container similar to the preceding label sets.
std::map<boost::container::flat_set<uint_fast64_t>, std::set<boost::container::flat_set<uint_fast64_t>>> backwardImplications;

3
src/generator/JaniNextStateGenerator.cpp

@ -161,6 +161,9 @@ namespace storm {
}
// Block the current initial state to search for the next one.
if (!blockingExpression.isInitialized()) {
break;
}
solver->add(blockingExpression);
}

11
src/generator/PrismNextStateGenerator.cpp

@ -23,8 +23,9 @@ namespace storm {
template<typename ValueType, typename StateType>
PrismNextStateGenerator<ValueType, StateType>::PrismNextStateGenerator(storm::prism::Program const& program, NextStateGeneratorOptions const& options, bool flag) : NextStateGenerator<ValueType, StateType>(program.getManager(), options), program(program), rewardModels() {
STORM_LOG_TRACE("Creating next-state generator for PRISM program: " << program);
STORM_LOG_THROW(!this->program.specifiesSystemComposition(), storm::exceptions::WrongFormatException, "The explicit next-state generator currently does not support custom system compositions.");
// Only after checking validity of the program, we initialize the variable information.
this->checkValid(program);
this->variableInformation = VariableInformation(program);
@ -136,7 +137,7 @@ namespace storm {
for (auto const& expression : rangeExpressions) {
solver->add(expression);
}
solver->add(program.getInitialConstruct().getInitialStatesExpression());
solver->add(program.getInitialStatesExpression());
// Proceed ss long as the solver can still enumerate initial states.
std::vector<StateType> initialStateIndices;
@ -166,6 +167,9 @@ namespace storm {
initialStateIndices.push_back(id);
// Block the current initial state to search for the next one.
if (!blockingExpression.isInitialized()) {
break;
}
solver->add(blockingExpression);
}
@ -314,7 +318,7 @@ namespace storm {
template<typename ValueType, typename StateType>
boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> PrismNextStateGenerator<ValueType, StateType>::getActiveCommandsByActionIndex(uint_fast64_t const& actionIndex) {
boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> result((std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>()));
// Iterate over all modules.
for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
storm::prism::Module const& module = program.getModule(i);
@ -445,7 +449,6 @@ namespace storm {
for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) {
storm::prism::Command const& command = *iteratorList[i];
for (uint_fast64_t j = 0; j < command.getNumberOfUpdates(); ++j) {
storm::prism::Update const& update = command.getUpdate(j);

1
src/modelchecker/AbstractModelChecker.cpp

@ -17,6 +17,7 @@
#include "src/models/symbolic/Mdp.h"
#include "src/models/sparse/MarkovAutomaton.h"
#include "src/models/sparse/StandardRewardModel.h"
#include "src/models/symbolic/StandardRewardModel.h"
#include "src/storage/dd/Add.h"
#include "src/storage/dd/Bdd.h"

32
src/parser/ExpressionParser.cpp

@ -3,6 +3,34 @@
#include "src/exceptions/InvalidTypeException.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/utility/constants.h"
namespace boost {
namespace spirit {
namespace traits {
template<>
bool scale(int exp, storm::RationalNumber& r, storm::RationalNumber acc) {
if (exp >= 0) {
r = acc * storm::utility::pow(storm::RationalNumber(10), static_cast<uint_fast64_t>(exp));
} else {
r = acc / storm::utility::pow(storm::RationalNumber(10), static_cast<uint_fast64_t>(-exp));
}
return true;
}
template<>
bool is_equal_to_one(storm::RationalNumber const& value) {
return storm::utility::isOne(value);
}
template<>
storm::RationalNumber negate(bool neg, storm::RationalNumber const& number) {
return neg ? storm::RationalNumber(-number) : number;
}
}
}
}
namespace storm {
namespace parser {
ExpressionParser::ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols<char, uint_fast64_t> const& invalidIdentifiers_, bool enableErrorHandling, bool allowBacktracking) : ExpressionParser::base_type(expression), orOperator_(), andOperator_(), equalityOperator_(), relationalOperator_(), plusOperator_(), multiplicationOperator_(), infixPowerOperator_(), unaryOperator_(), floorCeilOperator_(), minMaxOperator_(), prefixPowerOperator_(), trueFalse_(manager), manager(manager.getSharedPointer()), createExpressions(false), acceptDoubleLiterals(true), identifiers_(nullptr), invalidIdentifiers_(invalidIdentifiers_) {
@ -33,7 +61,7 @@ namespace storm {
identifierExpression = identifier[qi::_val = phoenix::bind(&ExpressionParser::getIdentifierExpression, phoenix::ref(*this), qi::_1, allowBacktracking, qi::_pass)];
identifierExpression.name("identifier expression");
literalExpression = trueFalse_[qi::_val = qi::_1] | strict_double[qi::_val = phoenix::bind(&ExpressionParser::createDoubleLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)] | qi::int_[qi::_val = phoenix::bind(&ExpressionParser::createIntegerLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)];
literalExpression = trueFalse_[qi::_val = qi::_1] | rationalLiteral_[qi::_val = phoenix::bind(&ExpressionParser::createRationalLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)] | qi::int_[qi::_val = phoenix::bind(&ExpressionParser::createIntegerLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)];
literalExpression.name("literal expression");
atomicExpression = floorCeilExpression | prefixPowerExpression | minMaxExpression | (qi::lit("(") >> expression >> qi::lit(")")) | literalExpression | identifierExpression;
@ -295,7 +323,7 @@ namespace storm {
return manager->boolean(false);
}
storm::expressions::Expression ExpressionParser::createDoubleLiteralExpression(double value, bool& pass) const {
storm::expressions::Expression ExpressionParser::createRationalLiteralExpression(storm::RationalNumber const& value, bool& pass) const {
// If we are not supposed to accept double expressions, we reject it by setting pass to false.
if (!this->acceptDoubleLiterals) {
pass = false;

16
src/parser/ExpressionParser.h

@ -8,8 +8,20 @@
#include "src/storage/expressions/Expression.h"
#include "src/storage/expressions/ExpressionManager.h"
#include "src/adapters/CarlAdapter.h"
namespace storm {
namespace parser {
template<typename NumberType>
struct RationalPolicies : boost::spirit::qi::strict_real_policies<NumberType> {
static const bool expect_dot = true;
template <typename It, typename Attr>
static bool parse_nan(It&, It const&, Attr&) { return false; }
template <typename It, typename Attr>
static bool parse_inf(It&, It const&, Attr&) { return false; }
};
class ExpressionParser : public qi::grammar<Iterator, storm::expressions::Expression(), Skipper> {
public:
/*!
@ -236,7 +248,7 @@ namespace storm {
qi::rule<Iterator, std::string(), Skipper> identifier;
// Parser that is used to recognize doubles only (as opposed to Spirit's double_ parser).
boost::spirit::qi::real_parser<double, boost::spirit::qi::strict_real_policies<double>> strict_double;
boost::spirit::qi::real_parser<storm::RationalNumber, RationalPolicies<storm::RationalNumber>> rationalLiteral_;
// Helper functions to create expressions.
storm::expressions::Expression createIteExpression(storm::expressions::Expression e1, storm::expressions::Expression e2, storm::expressions::Expression e3, bool& pass) const;
@ -248,7 +260,7 @@ namespace storm {
storm::expressions::Expression createMultExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2, bool& pass) const;
storm::expressions::Expression createPowerExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2, bool& pass) const;
storm::expressions::Expression createUnaryExpression(boost::optional<storm::expressions::OperatorType> const& operatorType, storm::expressions::Expression const& e1, bool& pass) const;
storm::expressions::Expression createDoubleLiteralExpression(double value, bool& pass) const;
storm::expressions::Expression createRationalLiteralExpression(storm::RationalNumber const& value, bool& pass) const;
storm::expressions::Expression createIntegerLiteralExpression(int value, bool& pass) const;
storm::expressions::Expression createMinimumMaximumExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2, bool& pass) const;
storm::expressions::Expression createFloorCeilExpression(storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e1, bool& pass) const;

3
src/parser/JaniParser.h

@ -42,7 +42,8 @@ namespace storm {
storm::jani::Property parseProperty(json const& propertyStructure);
storm::jani::Automaton parseAutomaton(json const& automatonStructure, storm::jani::Model const& parentModel);
std::shared_ptr<storm::jani::Variable> parseVariable(json const& variableStructure, std::string const& scopeDescription, bool prefWithScope = false);
storm::expressions::Expression parseExpression(json const& expressionStructure, std::string const& scopeDescription, std::unordered_map<std::string, std::shared_ptr<storm::jani::Variable>> const& localVars = {});
storm::expressions::Expression parseExpression(json const& expressionStructure, std::string const& scopeDescription, std::unordered_map<std::string, std::shared_ptr<storm::jani::Variable>> const& localVars = std::unordered_map<std::string, std::shared_ptr<storm::jani::Variable>>());
private:
std::shared_ptr<storm::jani::Constant> parseConstant(json const& constantStructure, std::string const& scopeDescription = "global");

20
src/parser/PrismParser.cpp

@ -65,6 +65,8 @@ namespace storm {
STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << lineNumber << " of file " << filename << ".");
}
STORM_LOG_TRACE("Parsed PRISM input: " << result);
return result;
}
@ -103,10 +105,10 @@ namespace storm {
formulaDefinition = (qi::lit("formula") > identifier > qi::lit("=") > expressionParser > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createFormula, phoenix::ref(*this), qi::_1, qi::_2)];
formulaDefinition.name("formula definition");
booleanVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("bool")) > ((qi::lit("init") > expressionParser) | qi::attr(manager->boolean(false))) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createBooleanVariable, phoenix::ref(*this), qi::_1, qi::_2)];
booleanVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("bool")) > -((qi::lit("init") > expressionParser[qi::_a = qi::_1]) | qi::attr(manager->boolean(false))) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createBooleanVariable, phoenix::ref(*this), qi::_1, qi::_a)];
booleanVariableDefinition.name("boolean variable definition");
integerVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("[")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), false)]) > expressionParser[qi::_a = qi::_1] > qi::lit("..") > expressionParser > qi::lit("]")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), true)] > -(qi::lit("init") > expressionParser[qi::_a = qi::_1]) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createIntegerVariable, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_a)];
integerVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("[")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), false)]) > expressionParser > qi::lit("..") > expressionParser > qi::lit("]")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), true)] > -(qi::lit("init") > expressionParser[qi::_a = qi::_1]) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createIntegerVariable, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_a)];
integerVariableDefinition.name("integer variable definition");
variableDefinition = (booleanVariableDefinition[phoenix::push_back(qi::_r1, qi::_1)] | integerVariableDefinition[phoenix::push_back(qi::_r2, qi::_1)]);
@ -208,7 +210,7 @@ namespace storm {
moduleDefinitionList %= +(moduleRenaming(qi::_r1) | moduleDefinition(qi::_r1))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::modules, qi::_r1), qi::_1)];
moduleDefinitionList.name("module list");
start = (qi::eps
start = (qi::eps[phoenix::bind(&PrismParser::removeInitialConstruct, phoenix::ref(*this), qi::_a)]
> modelTypeDefinition[phoenix::bind(&GlobalProgramInformation::modelType, qi::_a) = qi::_1]
> *(definedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_a), qi::_1)]
| undefinedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_a), qi::_1)]
@ -276,7 +278,7 @@ namespace storm {
return true;
}
bool PrismParser::addInitialStatesConstruct(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation) {
bool PrismParser::addInitialStatesConstruct(storm::expressions::Expression const& initialStatesExpression, GlobalProgramInformation& globalProgramInformation) {
STORM_LOG_THROW(!globalProgramInformation.hasInitialConstruct, storm::exceptions::WrongFormatException, "Parsing error in " << this->getFilename() << ", line " << get_line(qi::_3) << ": Program must not define two initial constructs.");
if (globalProgramInformation.hasInitialConstruct) {
return false;
@ -585,7 +587,7 @@ namespace storm {
auto const& renamingPair = renaming.find(variable.getName());
STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Parsing error in " << this->getFilename() << ", line " << get_line(qi::_3) << ": Boolean variable '" << variable.getName() << " was not renamed.");
booleanVariables.push_back(storm::prism::BooleanVariable(manager->getVariable(renamingPair->second), variable.getInitialValueExpression().substitute(expressionRenaming), this->getFilename(), get_line(qi::_1)));
booleanVariables.push_back(storm::prism::BooleanVariable(manager->getVariable(renamingPair->second), variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(), this->getFilename(), get_line(qi::_1)));
}
// Rename the integer variables.
@ -594,7 +596,7 @@ namespace storm {
auto const& renamingPair = renaming.find(variable.getName());
STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Parsing error in " << this->getFilename() << ", line " << get_line(qi::_3) << ": Integer variable '" << variable.getName() << " was not renamed.");
integerVariables.push_back(storm::prism::IntegerVariable(manager->getVariable(renamingPair->second), variable.getLowerBoundExpression().substitute(expressionRenaming), variable.getUpperBoundExpression().substitute(expressionRenaming), variable.getInitialValueExpression().substitute(expressionRenaming), this->getFilename(), get_line(qi::_1)));
integerVariables.push_back(storm::prism::IntegerVariable(manager->getVariable(renamingPair->second), variable.getLowerBoundExpression().substitute(expressionRenaming), variable.getUpperBoundExpression().substitute(expressionRenaming), variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(), this->getFilename(), get_line(qi::_1)));
}
// Rename commands.
@ -640,7 +642,11 @@ namespace storm {
}
storm::prism::Program PrismParser::createProgram(GlobalProgramInformation const& globalProgramInformation) const {
return storm::prism::Program(manager, globalProgramInformation.modelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables, globalProgramInformation.globalIntegerVariables, globalProgramInformation.formulas, globalProgramInformation.modules, globalProgramInformation.actionIndices, globalProgramInformation.rewardModels, globalProgramInformation.labels, secondRun && !globalProgramInformation.hasInitialConstruct ? boost::none : boost::optional<storm::prism::InitialConstruct>(storm::prism::InitialConstruct(manager->boolean(false))), globalProgramInformation.systemCompositionConstruct, this->getFilename(), 1, this->secondRun);
return storm::prism::Program(manager, globalProgramInformation.modelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables, globalProgramInformation.globalIntegerVariables, globalProgramInformation.formulas, globalProgramInformation.modules, globalProgramInformation.actionIndices, globalProgramInformation.rewardModels, globalProgramInformation.labels, secondRun && !globalProgramInformation.hasInitialConstruct ? boost::none : boost::make_optional(globalProgramInformation.initialConstruct), globalProgramInformation.systemCompositionConstruct, this->getFilename(), 1, this->secondRun);
}
void PrismParser::removeInitialConstruct(GlobalProgramInformation& globalProgramInformation) const {
globalProgramInformation.hasInitialConstruct = false;
}
} // namespace parser
} // namespace storm

6
src/parser/PrismParser.h

@ -188,7 +188,7 @@ namespace storm {
// Rules for variable definitions.
qi::rule<Iterator, qi::unused_type(std::vector<storm::prism::BooleanVariable>&, std::vector<storm::prism::IntegerVariable>&), Skipper> variableDefinition;
qi::rule<Iterator, storm::prism::BooleanVariable(), Skipper> booleanVariableDefinition;
qi::rule<Iterator, storm::prism::BooleanVariable(), qi::locals<storm::expressions::Expression>, Skipper> booleanVariableDefinition;
qi::rule<Iterator, storm::prism::IntegerVariable(), qi::locals<storm::expressions::Expression>, Skipper> integerVariableDefinition;
// Rules for command definitions.
@ -241,7 +241,7 @@ namespace storm {
// Helper methods used in the grammar.
bool isValidIdentifier(std::string const& identifier);
bool addInitialStatesConstruct(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation);
bool addInitialStatesConstruct(storm::expressions::Expression const& initialStatesExpression, GlobalProgramInformation& globalProgramInformation);
bool addSystemCompositionConstruct(std::shared_ptr<storm::prism::Composition> const& composition, GlobalProgramInformation& globalProgramInformation);
@ -274,6 +274,8 @@ namespace storm {
storm::prism::Module createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const;
storm::prism::Program createProgram(GlobalProgramInformation const& globalProgramInformation) const;
void removeInitialConstruct(GlobalProgramInformation& globalProgramInformation) const;
// An error handler function.
phoenix::function<SpiritErrorHandler> handler;
};

5
src/settings/modules/CoreSettings.cpp

@ -30,7 +30,6 @@ namespace storm {
const std::string CoreSettings::engineOptionShortName = "e";
const std::string CoreSettings::ddLibraryOptionName = "ddlib";
const std::string CoreSettings::cudaOptionName = "cuda";
const std::string CoreSettings::minMaxEquationSolvingTechniqueOptionName = "ndmethod";
CoreSettings::CoreSettings() : ModuleSettings(moduleName), engine(CoreSettings::Engine::Sparse) {
this->addOption(storm::settings::OptionBuilder(moduleName, counterexampleOptionName, false, "Generates a counterexample for the given PRCTL formulas if not satisfied by the model")
@ -57,10 +56,6 @@ namespace storm {
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of an SMT solver. Available are: z3 and mathsat.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(smtSolvers)).setDefaultValueString("z3").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName, statisticsOptionName, false, "Sets whether to display statistics if available.").setShortName(statisticsOptionShortName).build());
this->addOption(storm::settings::OptionBuilder(moduleName, cudaOptionName, false, "Sets whether to use CUDA to speed up computation time.").build());
std::vector<std::string> minMaxSolvingTechniques = {"vi", "value-iteration", "pi", "policy-iteration"};
this->addOption(storm::settings::OptionBuilder(moduleName, minMaxEquationSolvingTechniqueOptionName, false, "Sets which min/max linear equation solving technique is preferred.")
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of a min/max linear equation solving technique. Available are: value-iteration (vi) and policy-iteration (pi).").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(minMaxSolvingTechniques)).setDefaultValueString("vi").build()).build());
}
bool CoreSettings::isCounterexampleSet() const {

1
src/settings/modules/CoreSettings.h

@ -151,7 +151,6 @@ namespace storm {
static const std::string engineOptionShortName;
static const std::string ddLibraryOptionName;
static const std::string cudaOptionName;
static const std::string minMaxEquationSolvingTechniqueOptionName;
};
} // namespace modules

4
src/storage/expressions/BinaryNumericalFunctionExpression.cpp

@ -3,7 +3,7 @@
#include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
#include "src/storage/expressions/IntegerLiteralExpression.h"
#include "src/storage/expressions/DoubleLiteralExpression.h"
#include "src/storage/expressions/RationalLiteralExpression.h"
#include "src/storage/expressions/ExpressionVisitor.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidTypeException.h"
@ -102,7 +102,7 @@ namespace storm {
case OperatorType::Power: newValue = static_cast<int_fast64_t>(std::pow(firstOperandEvaluation, secondOperandEvaluation)); break;
case OperatorType::Divide: STORM_LOG_THROW(false, storm::exceptions::InvalidStateException, "Unable to simplify division."); break;
}
return std::shared_ptr<BaseExpression>(new DoubleLiteralExpression(this->getManager(), newValue));
return std::shared_ptr<BaseExpression>(new RationalLiteralExpression(this->getManager(), newValue));
}
}

39
src/storage/expressions/DoubleLiteralExpression.cpp

@ -1,39 +0,0 @@
#include "src/storage/expressions/DoubleLiteralExpression.h"
#include "src/storage/expressions/ExpressionManager.h"
#include "src/storage/expressions/ExpressionVisitor.h"
namespace storm {
namespace expressions {
DoubleLiteralExpression::DoubleLiteralExpression(ExpressionManager const& manager, double value) : BaseExpression(manager, manager.getRationalType()), value(value) {
// Intentionally left empty.
}
double DoubleLiteralExpression::evaluateAsDouble(Valuation const* valuation) const {
return this->getValue();
}
bool DoubleLiteralExpression::isLiteral() const {
return true;
}
void DoubleLiteralExpression::gatherVariables(std::set<storm::expressions::Variable>& variables) const {
return;
}
std::shared_ptr<BaseExpression const> DoubleLiteralExpression::simplify() const {
return this->shared_from_this();
}
boost::any DoubleLiteralExpression::accept(ExpressionVisitor& visitor) const {
return visitor.visit(*this);
}
double DoubleLiteralExpression::getValue() const {
return this->value;
}
void DoubleLiteralExpression::printToStream(std::ostream& stream) const {
stream << this->getValue();
}
}
}

53
src/storage/expressions/DoubleLiteralExpression.h

@ -1,53 +0,0 @@
#ifndef STORM_STORAGE_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_
#define STORM_STORAGE_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_
#include "src/storage/expressions/BaseExpression.h"
#include "src/utility/OsDetection.h"
namespace storm {
namespace expressions {
class DoubleLiteralExpression : public BaseExpression {
public:
/*!
* Creates an double literal expression with the given value.
*
* @param manager The manager responsible for this expression.
* @param value The value of the double literal.
*/
DoubleLiteralExpression(ExpressionManager const& manager, double value);
// Instantiate constructors and assignments with their default implementations.
DoubleLiteralExpression(DoubleLiteralExpression const& other) = default;
DoubleLiteralExpression& operator=(DoubleLiteralExpression const& other) = delete;
#ifndef WINDOWS
DoubleLiteralExpression(DoubleLiteralExpression&&) = default;
DoubleLiteralExpression& operator=(DoubleLiteralExpression&&) = delete;
#endif
virtual ~DoubleLiteralExpression() = default;
// Override base class methods.
virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
virtual bool isLiteral() const override;
virtual void gatherVariables(std::set<storm::expressions::Variable>& variables) const override;
virtual std::shared_ptr<BaseExpression const> simplify() const override;
virtual boost::any accept(ExpressionVisitor& visitor) const override;
/*!
* Retrieves the value of the double literal.
*
* @return The value of the double literal.
*/
double getValue() const;
protected:
// Override base class method.
virtual void printToStream(std::ostream& stream) const override;
private:
// The value of the double literal.
double value;
};
}
}
#endif /* STORM_STORAGE_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_ */

6
src/storage/expressions/ExpressionManager.cpp

@ -65,7 +65,11 @@ namespace storm {
}
Expression ExpressionManager::rational(double value) const {
return Expression(std::shared_ptr<BaseExpression>(new DoubleLiteralExpression(*this, value)));
return Expression(std::shared_ptr<BaseExpression>(new RationalLiteralExpression(*this, value)));
}
Expression ExpressionManager::rational(storm::RationalNumber const& value) const {
return Expression(std::shared_ptr<BaseExpression>(new RationalLiteralExpression(*this, value)));
}
bool ExpressionManager::operator==(ExpressionManager const& other) const {

9
src/storage/expressions/ExpressionManager.h

@ -10,6 +10,7 @@
#include "src/storage/expressions/Variable.h"
#include "src/storage/expressions/Expression.h"
#include "src/adapters/CarlAdapter.h"
#include "src/utility/OsDetection.h"
namespace storm {
@ -104,6 +105,14 @@ namespace storm {
* @return The resulting expression.
*/
Expression rational(double value) const;
/*!
* Creates an expression that characterizes the given rational literal.
*
* @param value The value of the rational literal.
* @return The resulting expression.
*/
Expression rational(storm::RationalNumber const& value) const;
/*!
* Compares the two expression managers for equality, which holds iff they are the very same object.

4
src/storage/expressions/ExpressionVisitor.h

@ -15,7 +15,7 @@ namespace storm {
class UnaryNumericalFunctionExpression;
class BooleanLiteralExpression;
class IntegerLiteralExpression;
class DoubleLiteralExpression;
class RationalLiteralExpression;
class ExpressionVisitor {
public:
@ -28,7 +28,7 @@ namespace storm {
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression) = 0;
virtual boost::any visit(BooleanLiteralExpression const& expression) = 0;
virtual boost::any visit(IntegerLiteralExpression const& expression) = 0;
virtual boost::any visit(DoubleLiteralExpression const& expression) = 0;
virtual boost::any visit(RationalLiteralExpression const& expression) = 0;
};
}
}

2
src/storage/expressions/Expressions.h

@ -4,7 +4,7 @@
#include "src/storage/expressions/BinaryRelationExpression.h"
#include "src/storage/expressions/BooleanLiteralExpression.h"
#include "src/storage/expressions/IntegerLiteralExpression.h"
#include "src/storage/expressions/DoubleLiteralExpression.h"
#include "src/storage/expressions/RationalLiteralExpression.h"
#include "src/storage/expressions/UnaryBooleanFunctionExpression.h"
#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
#include "src/storage/expressions/VariableExpression.h"

4
src/storage/expressions/LinearCoefficientVisitor.cpp

@ -151,8 +151,8 @@ namespace storm {
return VariableCoefficients(static_cast<double>(expression.getValue()));
}
boost::any LinearCoefficientVisitor::visit(DoubleLiteralExpression const& expression) {
return VariableCoefficients(expression.getValue());
boost::any LinearCoefficientVisitor::visit(RationalLiteralExpression const& expression) {
return VariableCoefficients(expression.getValueAsDouble());
}
}
}

2
src/storage/expressions/LinearCoefficientVisitor.h

@ -75,7 +75,7 @@ namespace storm {
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression) override;
virtual boost::any visit(BooleanLiteralExpression const& expression) override;
virtual boost::any visit(IntegerLiteralExpression const& expression) override;
virtual boost::any visit(DoubleLiteralExpression const& expression) override;
virtual boost::any visit(RationalLiteralExpression const& expression) override;
};
}
}

2
src/storage/expressions/LinearityCheckVisitor.cpp

@ -85,7 +85,7 @@ namespace storm {
return LinearityStatus::LinearWithoutVariables;
}
boost::any LinearityCheckVisitor::visit(DoubleLiteralExpression const& expression) {
boost::any LinearityCheckVisitor::visit(RationalLiteralExpression const& expression) {
return LinearityStatus::LinearWithoutVariables;
}
}

2
src/storage/expressions/LinearityCheckVisitor.h

@ -29,7 +29,7 @@ namespace storm {
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression) override;
virtual boost::any visit(BooleanLiteralExpression const& expression) override;
virtual boost::any visit(IntegerLiteralExpression const& expression) override;
virtual boost::any visit(DoubleLiteralExpression const& expression) override;
virtual boost::any visit(RationalLiteralExpression const& expression) override;
private:
enum class LinearityStatus { NonLinear, LinearContainsVariables, LinearWithoutVariables };

53
src/storage/expressions/RationalLiteralExpression.cpp

@ -0,0 +1,53 @@
#include "src/storage/expressions/RationalLiteralExpression.h"
#include "src/storage/expressions/ExpressionManager.h"
#include "src/storage/expressions/ExpressionVisitor.h"
#include "src/utility/constants.h"
namespace storm {
namespace expressions {
RationalLiteralExpression::RationalLiteralExpression(ExpressionManager const& manager, double value) : BaseExpression(manager, manager.getRationalType()), value(storm::utility::convertNumber<storm::RationalNumber>(value)) {
// Intentionally left empty.
}
RationalLiteralExpression::RationalLiteralExpression(ExpressionManager const& manager, std::string const& valueAsString) : BaseExpression(manager, manager.getRationalType()), value(storm::utility::convertNumber<storm::RationalNumber>(valueAsString)) {
// Intentionally left empty.
}
RationalLiteralExpression::RationalLiteralExpression(ExpressionManager const& manager, storm::RationalNumber const& value) : BaseExpression(manager, manager.getRationalType()), value(value) {
// Intentionally left empty.
}
double RationalLiteralExpression::evaluateAsDouble(Valuation const* valuation) const {
return this->getValueAsDouble();
}
bool RationalLiteralExpression::isLiteral() const {
return true;
}
void RationalLiteralExpression::gatherVariables(std::set<storm::expressions::Variable>& variables) const {
return;
}
std::shared_ptr<BaseExpression const> RationalLiteralExpression::simplify() const {
return this->shared_from_this();
}
boost::any RationalLiteralExpression::accept(ExpressionVisitor& visitor) const {
return visitor.visit(*this);
}
double RationalLiteralExpression::getValueAsDouble() const {
return storm::utility::convertNumber<double>(this->value);
}
storm::RationalNumber RationalLiteralExpression::getValue() const {
return this->value;
}
void RationalLiteralExpression::printToStream(std::ostream& stream) const {
stream << this->getValue();
}
}
}

78
src/storage/expressions/RationalLiteralExpression.h

@ -0,0 +1,78 @@
#ifndef STORM_STORAGE_EXPRESSIONS_RationalLiteralExpression_H_
#define STORM_STORAGE_EXPRESSIONS_RationalLiteralExpression_H_
#include "src/storage/expressions/BaseExpression.h"
#include "src/utility/OsDetection.h"
#include "src/adapters/CarlAdapter.h"
namespace storm {
namespace expressions {
class RationalLiteralExpression : public BaseExpression {
public:
/*!
* Creates an double literal expression with the given value.
*
* @param manager The manager responsible for this expression.
* @param value The value of the double literal.
*/
RationalLiteralExpression(ExpressionManager const& manager, double value);
/*!
* Creates an double literal expression with the value given as a string.
*
* @param manager The manager responsible for this expression.
* @param value The string representation of the value of the literal.
*/
RationalLiteralExpression(ExpressionManager const& manager, std::string const& valueAsString);
/*!
* Creates an double literal expression with the rational value.
*
* @param manager The manager responsible for this expression.
* @param value The rational number that is the value of this literal expression.
*/
RationalLiteralExpression(ExpressionManager const& manager, storm::RationalNumber const& value);
// Instantiate constructors and assignments with their default implementations.
RationalLiteralExpression(RationalLiteralExpression const& other) = default;
RationalLiteralExpression& operator=(RationalLiteralExpression const& other) = delete;
#ifndef WINDOWS
RationalLiteralExpression(RationalLiteralExpression&&) = default;
RationalLiteralExpression& operator=(RationalLiteralExpression&&) = delete;
#endif
virtual ~RationalLiteralExpression() = default;
// Override base class methods.
virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
virtual bool isLiteral() const override;
virtual void gatherVariables(std::set<storm::expressions::Variable>& variables) const override;
virtual std::shared_ptr<BaseExpression const> simplify() const override;
virtual boost::any accept(ExpressionVisitor& visitor) const override;
/*!
* Retrieves the value of the double literal.
*
* @return The value of the double literal.
*/
double getValueAsDouble() const;
/*!
* Retrieves the value of the double literal.
*
* @return The value of the double literal.
*/
storm::RationalNumber getValue() const;
protected:
// Override base class method.
virtual void printToStream(std::ostream& stream) const override;
private:
// The value of the literal.
storm::RationalNumber value;
};
}
}
#endif /* STORM_STORAGE_EXPRESSIONS_RationalLiteralExpression_H_ */

2
src/storage/expressions/SubstitutionVisitor.cpp

@ -116,7 +116,7 @@ namespace storm {
}
template<typename MapType>
boost::any SubstitutionVisitor<MapType>::visit(DoubleLiteralExpression const& expression) {
boost::any SubstitutionVisitor<MapType>::visit(RationalLiteralExpression const& expression) {
return expression.getSharedPointer();
}

2
src/storage/expressions/SubstitutionVisitor.h

@ -37,7 +37,7 @@ namespace storm {
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression) override;
virtual boost::any visit(BooleanLiteralExpression const& expression) override;
virtual boost::any visit(IntegerLiteralExpression const& expression) override;
virtual boost::any visit(DoubleLiteralExpression const& expression) override;
virtual boost::any visit(RationalLiteralExpression const& expression) override;
private:
// A mapping of variables to expressions with which they shall be replaced.

2
src/storage/expressions/ToExprtkStringVisitor.cpp

@ -212,7 +212,7 @@ namespace storm {
return boost::any();
}
boost::any ToExprtkStringVisitor::visit(DoubleLiteralExpression const& expression) {
boost::any ToExprtkStringVisitor::visit(RationalLiteralExpression const& expression) {
stream << expression.getValue();
return boost::any();
}

2
src/storage/expressions/ToExprtkStringVisitor.h

@ -25,7 +25,7 @@ namespace storm {
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression) override;
virtual boost::any visit(BooleanLiteralExpression const& expression) override;
virtual boost::any visit(IntegerLiteralExpression const& expression) override;
virtual boost::any visit(DoubleLiteralExpression const& expression) override;
virtual boost::any visit(RationalLiteralExpression const& expression) override;
private:
std::stringstream stream;

11
src/storage/expressions/ToRationalFunctionVisitor.cpp

@ -2,6 +2,7 @@
#include <sstream>
#include "src/utility/constants.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidArgumentException.h"
@ -33,6 +34,7 @@ namespace storm {
boost::any ToRationalFunctionVisitor<RationalFunctionType>::visit(BinaryNumericalFunctionExpression const& expression) {
RationalFunctionType firstOperandAsRationalFunction = boost::any_cast<RationalFunctionType>(expression.getFirstOperand()->accept(*this));
RationalFunctionType secondOperandAsRationalFunction = boost::any_cast<RationalFunctionType>(expression.getSecondOperand()->accept(*this));
uint_fast64_t exponentAsInteger = 0;
switch(expression.getOperatorType()) {
case BinaryNumericalFunctionExpression::OperatorType::Plus:
return firstOperandAsRationalFunction + secondOperandAsRationalFunction;
@ -46,6 +48,11 @@ namespace storm {
case BinaryNumericalFunctionExpression::OperatorType::Divide:
return firstOperandAsRationalFunction / secondOperandAsRationalFunction;
break;
case BinaryNumericalFunctionExpression::OperatorType::Power:
STORM_LOG_THROW(storm::utility::isInteger(secondOperandAsRationalFunction), storm::exceptions::InvalidArgumentException, "Exponent of power operator must be a positive integer.");
exponentAsInteger = storm::utility::convertNumber<uint_fast64_t>(secondOperandAsRationalFunction);
return storm::utility::pow(firstOperandAsRationalFunction, exponentAsInteger);
break;
default:
STORM_LOG_ASSERT(false, "Illegal operator type.");
}
@ -92,8 +99,8 @@ namespace storm {
}
template<typename RationalFunctionType>
boost::any ToRationalFunctionVisitor<RationalFunctionType>::visit(DoubleLiteralExpression const& expression) {
return RationalFunctionType(carl::rationalize<storm::RationalNumber>(expression.getValue()));
boost::any ToRationalFunctionVisitor<RationalFunctionType>::visit(RationalLiteralExpression const& expression) {
return storm::utility::convertNumber<storm::RationalFunction>(expression.getValue());
}
template class ToRationalFunctionVisitor<storm::RationalFunction>;

2
src/storage/expressions/ToRationalFunctionVisitor.h

@ -27,7 +27,7 @@ namespace storm {
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression) override;
virtual boost::any visit(BooleanLiteralExpression const& expression) override;
virtual boost::any visit(IntegerLiteralExpression const& expression) override;
virtual boost::any visit(DoubleLiteralExpression const& expression) override;
virtual boost::any visit(RationalLiteralExpression const& expression) override;
private:
template<typename TP = typename RationalFunctionType::PolyType, carl::EnableIf<carl::needs_cache<TP>> = carl::dummy>

31
src/storage/expressions/ToRationalNumberVisitor.cpp

@ -1,6 +1,7 @@
#include "src/storage/expressions/ToRationalNumberVisitor.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
#include "src/exceptions/InvalidArgumentException.h"
#include "src/exceptions/NotSupportedException.h"
@ -28,26 +29,36 @@ namespace storm {
template<typename RationalNumberType>
boost::any ToRationalNumberVisitor<RationalNumberType>::visit(BinaryNumericalFunctionExpression const& expression) {
RationalNumberType firstOperandAsRationalFunction = boost::any_cast<RationalNumberType>(expression.getFirstOperand()->accept(*this));
RationalNumberType secondOperandAsRationalFunction = boost::any_cast<RationalNumberType>(expression.getSecondOperand()->accept(*this));
RationalNumberType firstOperandAsRationalNumber = boost::any_cast<RationalNumberType>(expression.getFirstOperand()->accept(*this));
RationalNumberType secondOperandAsRationalNumber = boost::any_cast<RationalNumberType>(expression.getSecondOperand()->accept(*this));
switch(expression.getOperatorType()) {
case BinaryNumericalFunctionExpression::OperatorType::Plus:
return firstOperandAsRationalFunction + secondOperandAsRationalFunction;
return firstOperandAsRationalNumber + secondOperandAsRationalNumber;
break;
case BinaryNumericalFunctionExpression::OperatorType::Minus:
return firstOperandAsRationalFunction - secondOperandAsRationalFunction;
return firstOperandAsRationalNumber - secondOperandAsRationalNumber;
break;
case BinaryNumericalFunctionExpression::OperatorType::Times:
return firstOperandAsRationalFunction * secondOperandAsRationalFunction;
return firstOperandAsRationalNumber * secondOperandAsRationalNumber;
break;
case BinaryNumericalFunctionExpression::OperatorType::Divide:
return firstOperandAsRationalFunction / secondOperandAsRationalFunction;
return firstOperandAsRationalNumber / secondOperandAsRationalNumber;
break;
case BinaryNumericalFunctionExpression::OperatorType::Min:
return std::min(firstOperandAsRationalNumber, secondOperandAsRationalNumber);
break;
case BinaryNumericalFunctionExpression::OperatorType::Max:
return std::max(firstOperandAsRationalNumber, secondOperandAsRationalNumber);
break;
case BinaryNumericalFunctionExpression::OperatorType::Power:
STORM_LOG_THROW(storm::utility::isInteger(secondOperandAsRationalNumber), storm::exceptions::InvalidArgumentException, "Exponent of power operator must be a positive integer.");
uint_fast64_t exponentAsInteger = storm::utility::convertNumber<uint_fast64_t>(secondOperandAsRationalNumber);
return storm::utility::pow(firstOperandAsRationalNumber, exponentAsInteger);
break;
default:
STORM_LOG_ASSERT(false, "Illegal operator type.");
}
// Return a dummy. This point must, however, never be reached.
STORM_LOG_ASSERT(false, "Illegal operator type.");
return boost::any();
}
@ -86,9 +97,9 @@ namespace storm {
}
template<typename RationalNumberType>
boost::any ToRationalNumberVisitor<RationalNumberType>::visit(DoubleLiteralExpression const& expression) {
boost::any ToRationalNumberVisitor<RationalNumberType>::visit(RationalLiteralExpression const& expression) {
#ifdef STORM_HAVE_CARL
return RationalNumberType(carl::rationalize<storm::RationalNumber>(expression.getValue()));
return expression.getValue();
#else
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Rational numbers are not supported in this build.");
#endif

2
src/storage/expressions/ToRationalNumberVisitor.h

@ -25,7 +25,7 @@ namespace storm {
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression) override;
virtual boost::any visit(BooleanLiteralExpression const& expression) override;
virtual boost::any visit(IntegerLiteralExpression const& expression) override;
virtual boost::any visit(DoubleLiteralExpression const& expression) override;
virtual boost::any visit(RationalLiteralExpression const& expression) override;
};
}
}

4
src/storage/expressions/UnaryNumericalFunctionExpression.cpp

@ -4,7 +4,7 @@
#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
#include "src/storage/expressions/IntegerLiteralExpression.h"
#include "src/storage/expressions/DoubleLiteralExpression.h"
#include "src/storage/expressions/RationalLiteralExpression.h"
#include "ExpressionVisitor.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidTypeException.h"
@ -87,7 +87,7 @@ namespace storm {
case OperatorType::Floor: value = std::floor(boost::get<double>(operandEvaluation)); break;
case OperatorType::Ceil: value = std::ceil(boost::get<double>(operandEvaluation)); break;
}
return std::shared_ptr<BaseExpression>(new DoubleLiteralExpression(this->getManager(), value));
return std::shared_ptr<BaseExpression>(new RationalLiteralExpression(this->getManager(), value));
}
}

9
src/storage/jani/BooleanVariable.cpp

@ -11,10 +11,17 @@ namespace storm {
// Intentionally left empty.
}
bool BooleanVariable::isBooleanVariable() const {
return true;
}
std::shared_ptr<BooleanVariable> makeBooleanVariable(std::string const& name, storm::expressions::Variable const& variable, boost::optional<storm::expressions::Expression> initValue, bool transient) {
if (initValue) {
return std::make_shared<BooleanVariable>(name, variable, initValue.get(), transient);
} else {
return std::make_shared<BooleanVariable>(name, variable, transient);
}
}
}
}

5
src/storage/jani/BooleanVariable.h

@ -21,5 +21,10 @@ namespace storm {
virtual bool isBooleanVariable() const override;
};
/**
* Convenience function to call the appropriate constructor and return a shared pointer to the variable.
*/
std::shared_ptr<BooleanVariable> makeBooleanVariable(std::string const& name, storm::expressions::Variable const& variable, boost::optional<storm::expressions::Expression> initValue, bool transient);
}
}

6
src/storage/jani/BoundedIntegerVariable.cpp

@ -47,10 +47,8 @@ namespace storm {
}
std::shared_ptr<BoundedIntegerVariable> makeBoundedIntegerVariable(std::string const& name, storm::expressions::Variable const& variable, boost::optional<storm::expressions::Expression> initValue, bool transient, boost::optional<storm::expressions::Expression> lowerBound, boost::optional<storm::expressions::Expression> upperBound) {
if(!lowerBound || !upperBound) {
STORM_LOG_THROW(lowerBound && upperBound, storm::exceptions::NotImplementedException, "Jani Bounded Integer variables (for now) have to be bounded from both sides");
}
if(initValue) {
STORM_LOG_THROW(lowerBound && upperBound, storm::exceptions::NotImplementedException, "Jani Bounded Integer variables (for now) have to be bounded from both sides");
if (initValue) {
return std::make_shared<BoundedIntegerVariable>(name, variable, initValue.get(), transient, lowerBound.get(), upperBound.get());
} else {
return std::make_shared<BoundedIntegerVariable>(name, variable, transient, lowerBound.get(), upperBound.get());

2
src/storage/jani/BoundedIntegerVariable.h

@ -61,7 +61,7 @@ namespace storm {
};
/**
* Convenience function to call the appropriate constructor and retur a shared pointer to the variable.
* Convenience function to call the appropriate constructor and return a shared pointer to the variable.
*/
std::shared_ptr<BoundedIntegerVariable> makeBoundedIntegerVariable(std::string const& name, storm::expressions::Variable const& variable, boost::optional<storm::expressions::Expression> initValue, bool transient, boost::optional<storm::expressions::Expression> lowerBound, boost::optional<storm::expressions::Expression> upperBound);
}

1
src/storage/jani/UnboundedIntegerVariable.h

@ -15,7 +15,6 @@ namespace storm {
* Creates an unbounded integer variable with initial value.
*/
UnboundedIntegerVariable(std::string const& name, storm::expressions::Variable const& variable, storm::expressions::Expression const&, bool transient=false);
virtual bool isUnboundedIntegerVariable() const override;
};

16
src/storage/prism/BooleanVariable.cpp

@ -1,5 +1,7 @@
#include "src/storage/prism/BooleanVariable.h"
#include "src/storage/expressions/ExpressionManager.h"
namespace storm {
namespace prism {
BooleanVariable::BooleanVariable(storm::expressions::Variable const& variable, storm::expressions::Expression const& initialValueExpression, std::string const& filename, uint_fast64_t lineNumber) : Variable(variable, initialValueExpression, false, filename, lineNumber) {
@ -7,11 +9,21 @@ namespace storm {
}
BooleanVariable BooleanVariable::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return BooleanVariable(this->getExpressionVariable(), this->getInitialValueExpression().substitute(substitution), this->getFilename(), this->getLineNumber());
return BooleanVariable(this->getExpressionVariable(), this->getInitialValueExpression().isInitialized() ? this->getInitialValueExpression().substitute(substitution) : this->getInitialValueExpression(), this->getFilename(), this->getLineNumber());
}
void BooleanVariable::createMissingInitialValue() {
if (!this->hasInitialValue()) {
this->setInitialValueExpression(this->getExpressionVariable().getManager().boolean(false));
}
}
std::ostream& operator<<(std::ostream& stream, BooleanVariable const& variable) {
stream << variable.getName() << ": bool init " << variable.getInitialValueExpression() << ";";
stream << variable.getName() << ": bool";
if (variable.hasInitialValue()) {
stream << " init " << variable.getInitialValueExpression();
}
stream << ";";
return stream;
}

2
src/storage/prism/BooleanVariable.h

@ -37,6 +37,8 @@ namespace storm {
*/
BooleanVariable substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const;
virtual void createMissingInitialValue() override;
friend std::ostream& operator<<(std::ostream& stream, BooleanVariable const& variable);
};

7
src/storage/prism/Constant.cpp

@ -42,7 +42,12 @@ namespace storm {
}
std::ostream& operator<<(std::ostream& stream, Constant const& constant) {
stream << "const " << constant.getExpressionVariable().getType() << " ";
stream << "const ";
if (constant.getType().isRationalType()) {
stream << "double" << " ";
} else {
stream << constant.getType() << " ";
}
stream << constant.getName();
if (constant.isDefined()) {
stream << " = " << constant.getExpression();

14
src/storage/prism/IntegerVariable.cpp

@ -19,11 +19,21 @@ namespace storm {
}
IntegerVariable IntegerVariable::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return IntegerVariable(this->getExpressionVariable(), this->getLowerBoundExpression().substitute(substitution), this->getUpperBoundExpression().substitute(substitution), this->getInitialValueExpression().substitute(substitution), this->getFilename(), this->getLineNumber());
return IntegerVariable(this->getExpressionVariable(), this->getLowerBoundExpression().substitute(substitution), this->getUpperBoundExpression().substitute(substitution), this->getInitialValueExpression().isInitialized() ? this->getInitialValueExpression().substitute(substitution) : this->getInitialValueExpression(), this->getFilename(), this->getLineNumber());
}
void IntegerVariable::createMissingInitialValue() {
if (!this->hasInitialValue()) {
this->setInitialValueExpression(this->getLowerBoundExpression());
}
}
std::ostream& operator<<(std::ostream& stream, IntegerVariable const& variable) {
stream << variable.getName() << ": [" << variable.getLowerBoundExpression() << ".." << variable.getUpperBoundExpression() << "]" << " init " << variable.getInitialValueExpression() << ";";
stream << variable.getName() << ": [" << variable.getLowerBoundExpression() << ".." << variable.getUpperBoundExpression() << "]";
if (variable.hasInitialValue()) {
stream << " init " << variable.getInitialValueExpression();
}
stream << ";";
return stream;
}
} // namespace prism

2
src/storage/prism/IntegerVariable.h

@ -60,6 +60,8 @@ namespace storm {
*/
IntegerVariable substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const;
virtual void createMissingInitialValue() override;
friend std::ostream& operator<<(std::ostream& stream, IntegerVariable const& variable);
private:

20
src/storage/prism/Module.cpp

@ -42,7 +42,7 @@ namespace storm {
std::vector<storm::prism::IntegerVariable> const& Module::getIntegerVariables() const {
return this->integerVariables;
}
std::set<storm::expressions::Variable> Module::getAllExpressionVariables() const {
std::set<storm::expressions::Variable> result;
for (auto const& var : this->getBooleanVariables()) {
@ -188,10 +188,7 @@ namespace storm {
std::vector<Command> newCommands;
newCommands.reserve(this->getNumberOfCommands());
for (auto const& command : this->getCommands()) {
Command newCommand = command.substitute(substitution);
if (!newCommand.getGuardExpression().isFalse()) {
newCommands.emplace_back(newCommand);
}
newCommands.emplace_back(command.substitute(substitution));
}
return Module(this->getName(), newBooleanVariables, newIntegerVariables, newCommands, this->getFilename(), this->getLineNumber());
@ -216,12 +213,23 @@ namespace storm {
}
for (auto const& command : this->getCommands()) {
command.containsVariablesOnlyInUpdateProbabilities(undefinedConstantVariables);
if (!command.containsVariablesOnlyInUpdateProbabilities(undefinedConstantVariables)) {
return false;
}
}
return true;
}
void Module::createMissingInitialValues() {
for (auto& variable : booleanVariables) {
variable.createMissingInitialValue();
}
for (auto& variable : integerVariables) {
variable.createMissingInitialValue();
}
}
std::ostream& operator<<(std::ostream& stream, Module const& module) {
stream << "module " << module.getName() << std::endl;
for (auto const& booleanVariable : module.getBooleanVariables()) {

6
src/storage/prism/Module.h

@ -104,7 +104,6 @@ namespace storm {
*/
std::set<storm::expressions::Variable> getAllExpressionVariables() const;
/*!
* Retrieves a list of expressions that characterize the legal ranges of all variables declared by this
* module.
@ -226,6 +225,11 @@ namespace storm {
*/
bool containsVariablesOnlyInUpdateProbabilities(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const;
/*!
* Equips all of the modules' variables without initial values with initial values based on their type.
*/
void createMissingInitialValues();
friend std::ostream& operator<<(std::ostream& stream, Module const& module);
private:

379
src/storage/prism/Program.cpp

@ -148,28 +148,15 @@ namespace storm {
// Start by creating the necessary mappings from the given ones.
this->createMappings();
// Set the initial construct.
// Set the initial construct if given.
if (initialConstruct) {
this->initialConstruct = initialConstruct.get();
} else {
// Create a new initial construct if none was given.
storm::expressions::Expression newInitialExpression = manager->boolean(true);
for (auto const& booleanVariable : this->getGlobalBooleanVariables()) {
newInitialExpression = newInitialExpression && storm::expressions::iff(booleanVariable.getExpression(), booleanVariable.getInitialValueExpression());
}
for (auto const& integerVariable : this->getGlobalIntegerVariables()) {
newInitialExpression = newInitialExpression && integerVariable.getExpression() == integerVariable.getInitialValueExpression();
}
for (auto const& module : this->getModules()) {
for (auto const& booleanVariable : module.getBooleanVariables()) {
newInitialExpression = newInitialExpression && storm::expressions::iff(booleanVariable.getExpression(), booleanVariable.getInitialValueExpression());
}
for (auto const& integerVariable : module.getIntegerVariables()) {
newInitialExpression = newInitialExpression && integerVariable.getExpression() == integerVariable.getInitialValueExpression();
}
// Otherwise, we create the missing initial values.
this->createMissingInitialValues();
for (auto& modules : this->modules) {
modules.createMissingInitialValues();
}
this->initialConstruct = storm::prism::InitialConstruct(newInitialExpression, this->getInitialConstruct().getFilename(), this->getInitialConstruct().getLineNumber());
}
if (finalModel) {
@ -230,7 +217,7 @@ namespace storm {
// constants' variables is empty (except for the update probabilities).
// Start by checking the defining expressions of all defined constants. If it contains a currently undefined
//constant, we need to mark the target constant as undefined as well.
// constant, we need to mark the target constant as undefined as well.
for (auto const& constant : this->getConstants()) {
if (constant.isDefined()) {
if (constant.getExpression().containsVariable(undefinedConstantVariables)) {
@ -241,13 +228,17 @@ namespace storm {
// Now check initial value expressions of global variables.
for (auto const& booleanVariable : this->getGlobalBooleanVariables()) {
if (booleanVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
return false;
if (booleanVariable.hasInitialValue()) {
if (booleanVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
return false;
}
}
}
for (auto const& integerVariable : this->getGlobalIntegerVariables()) {
if (integerVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
return false;
if (integerVariable.hasInitialValue()) {
if (integerVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
return false;
}
}
if (integerVariable.getLowerBoundExpression().containsVariable(undefinedConstantVariables)) {
return false;
@ -266,7 +257,9 @@ namespace storm {
// Proceed by checking each of the modules.
for (auto const& module : this->getModules()) {
module.containsVariablesOnlyInUpdateProbabilities(undefinedConstantVariables);
if (!module.containsVariablesOnlyInUpdateProbabilities(undefinedConstantVariables)) {
return false;
}
}
// Check the reward models.
@ -275,8 +268,10 @@ namespace storm {
}
// Initial construct.
if (this->getInitialConstruct().getInitialStatesExpression().containsVariable(undefinedConstantVariables)) {
return false;
if (this->hasInitialConstruct()) {
if (this->getInitialConstruct().getInitialStatesExpression().containsVariable(undefinedConstantVariables)) {
return false;
}
}
// Labels.
@ -446,10 +441,61 @@ namespace storm {
return actionToIndexMap;
}
bool Program::hasInitialConstruct() const {
return static_cast<bool>(initialConstruct);
}
storm::prism::InitialConstruct const& Program::getInitialConstruct() const {
return this->initialConstruct.get();
}
boost::optional<InitialConstruct> const& Program::getOptionalInitialConstruct() const {
return this->initialConstruct;
}
storm::expressions::Expression Program::getInitialStatesExpression() const {
// If there is an initial construct, return its expression. If not, we construct the expression from the
// initial values of the variables (which have to exist).
if (this->hasInitialConstruct()) {
return this->getInitialConstruct().getInitialStatesExpression();
} else {
storm::expressions::Expression result;
for (auto const& variable : this->getGlobalBooleanVariables()) {
if (result.isInitialized()) {
result = result && storm::expressions::iff(variable.getExpressionVariable(), variable.getInitialValueExpression());
} else {
result = storm::expressions::iff(variable.getExpressionVariable(), variable.getInitialValueExpression());
}
}
for (auto const& variable : this->getGlobalIntegerVariables()) {
if (result.isInitialized()) {
result = result && variable.getExpressionVariable() == variable.getInitialValueExpression();
} else {
result = variable.getExpressionVariable() == variable.getInitialValueExpression();
}
}
for (auto const& module : this->getModules()) {
for (auto const& variable : module.getBooleanVariables()) {
if (result.isInitialized()) {
result = result && storm::expressions::iff(variable.getExpressionVariable(), variable.getInitialValueExpression());
} else {
result = storm::expressions::iff(variable.getExpressionVariable(), variable.getInitialValueExpression());
}
}
for (auto const& variable : module.getIntegerVariables()) {
if (result.isInitialized()) {
result = result && variable.getExpressionVariable() == variable.getInitialValueExpression();
} else {
result = variable.getExpressionVariable() == variable.getInitialValueExpression();
}
}
}
return result;
}
}
bool Program::specifiesSystemComposition() const {
return static_cast<bool>(systemCompositionConstruct);
}
@ -611,7 +657,7 @@ namespace storm {
newModules.push_back(module.restrictCommands(indexSet));
}
return Program(this->manager, this->getModelType(), this->getConstants(), this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), newModules, this->getActionNameToIndexMapping(), this->getRewardModels(), this->getLabels(), this->getInitialConstruct(), this->getOptionalSystemCompositionConstruct());
return Program(this->manager, this->getModelType(), this->getConstants(), this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), newModules, this->getActionNameToIndexMapping(), this->getRewardModels(), this->getLabels(), this->getOptionalInitialConstruct(), this->getOptionalSystemCompositionConstruct());
}
void Program::createMappings() {
@ -711,11 +757,11 @@ namespace storm {
STORM_LOG_THROW(definedUndefinedConstants.find(constantExpressionPair.first) != definedUndefinedConstants.end(), storm::exceptions::InvalidArgumentException, "Unable to define non-existant constant.");
}
return Program(this->manager, this->getModelType(), newConstants, this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), this->getModules(), this->getActionNameToIndexMapping(), this->getRewardModels(), this->getLabels(), this->getInitialConstruct(), this->getOptionalSystemCompositionConstruct());
return Program(this->manager, this->getModelType(), newConstants, this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), this->getModules(), this->getActionNameToIndexMapping(), this->getRewardModels(), this->getLabels(), this->getOptionalInitialConstruct(), this->getOptionalSystemCompositionConstruct());
}
Program Program::substituteConstants() const {
// We start by creating the appropriate substitution
// We start by creating the appropriate substitution.
std::map<storm::expressions::Variable, storm::expressions::Expression> constantSubstitution;
std::vector<Constant> newConstants(this->getConstants());
for (uint_fast64_t constantIndex = 0; constantIndex < newConstants.size(); ++constantIndex) {
@ -763,7 +809,10 @@ namespace storm {
newRewardModels.emplace_back(rewardModel.substitute(constantSubstitution));
}
storm::prism::InitialConstruct newInitialConstruct = this->getInitialConstruct().substitute(constantSubstitution);
boost::optional<storm::prism::InitialConstruct> newInitialConstruct;
if (this->hasInitialConstruct()) {
newInitialConstruct = this->getInitialConstruct().substitute(constantSubstitution);
}
std::vector<Label> newLabels;
newLabels.reserve(this->getNumberOfLabels());
@ -807,18 +856,22 @@ namespace storm {
// Now we check the variable declarations. We start with the global variables.
std::set<storm::expressions::Variable> variables;
for (auto const& variable : this->getGlobalBooleanVariables()) {
// Check the initial value of the variable.
std::set<storm::expressions::Variable> containedVariables = variable.getInitialValueExpression().getVariables();
std::set<storm::expressions::Variable> illegalVariables;
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
bool isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
if (variable.hasInitialValue()) {
STORM_LOG_THROW(!this->hasInitialConstruct(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": illegal to specify initial value if an initial construct is present.");
// Check the initial value of the variable.
std::set<storm::expressions::Variable> containedVariables = variable.getInitialValueExpression().getVariables();
std::set<storm::expressions::Variable> illegalVariables;
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
bool isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
// Record the new identifier for future checks.
@ -853,16 +906,20 @@ namespace storm {
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": upper bound expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
// Check the initial value of the variable.
containedVariables = variable.getInitialValueExpression().getVariables();
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
if (variable.hasInitialValue()) {
STORM_LOG_THROW(!this->hasInitialConstruct(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": illegal to specify initial value if an initial construct is present.");
// Check the initial value of the variable.
containedVariables = variable.getInitialValueExpression().getVariables();
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
// Record the new identifier for future checks.
@ -875,17 +932,21 @@ namespace storm {
// Now go through the variables of the modules.
for (auto const& module : this->getModules()) {
for (auto const& variable : module.getBooleanVariables()) {
// Check the initial value of the variable.
std::set<storm::expressions::Variable> containedVariables = variable.getInitialValueExpression().getVariables();
std::set<storm::expressions::Variable> illegalVariables;
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
bool isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
if (variable.hasInitialValue()) {
STORM_LOG_THROW(!this->hasInitialConstruct(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": illegal to specify initial value if an initial construct is present.");
// Check the initial value of the variable.
std::set<storm::expressions::Variable> containedVariables = variable.getInitialValueExpression().getVariables();
std::set<storm::expressions::Variable> illegalVariables;
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
bool isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
// Record the new identifier for future checks.
@ -918,17 +979,21 @@ namespace storm {
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": upper bound expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
// Check the initial value of the variable.
containedVariables = variable.getInitialValueExpression().getVariables();
illegalVariables.clear();
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
if (variable.hasInitialValue()) {
STORM_LOG_THROW(!this->hasInitialConstruct(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": illegal to specify initial value if an initial construct is present.");
// Check the initial value of the variable.
containedVariables = variable.getInitialValueExpression().getVariables();
illegalVariables.clear();
std::set_difference(containedVariables.begin(), containedVariables.end(), constants.begin(), constants.end(), std::inserter(illegalVariables, illegalVariables.begin()));
isValid = illegalVariables.empty();
if (!isValid) {
std::vector<std::string> illegalVariableNames;
for (auto const& var : illegalVariables) {
illegalVariableNames.push_back(var.getName());
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants: " << boost::algorithm::join(illegalVariableNames, ",") << ".");
}
// Record the new identifier for future checks.
@ -1091,9 +1156,11 @@ namespace storm {
}
// Check the initial states expression.
std::set<storm::expressions::Variable> containedIdentifiers = this->getInitialConstruct().getInitialStatesExpression().getVariables();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << this->getInitialConstruct().getFilename() << ", line " << this->getInitialConstruct().getLineNumber() << ": initial expression refers to unknown identifiers.");
if (this->hasInitialConstruct()) {
std::set<storm::expressions::Variable> containedIdentifiers = this->getInitialConstruct().getInitialStatesExpression().getVariables();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << this->getInitialConstruct().getFilename() << ", line " << this->getInitialConstruct().getLineNumber() << ": initial construct refers to unknown identifiers.");
}
// Check the system composition if given.
if (systemCompositionConstruct) {
@ -1151,17 +1218,28 @@ namespace storm {
}
Program Program::simplify() {
// Start by substituting the constants, because this will potentially erase some commands or even actions.
Program substitutedProgram = this->substituteConstants();
// As we possibly delete some commands and some actions might be dropped from modules altogether, we need to
// maintain a list of actions that we need to remove in other modules. For example, if module A loses all [a]
// commands, we need to delete all [a] commands from all other modules as well. If we do not do that, we will
// remove the forced synchronization that was there before.
std::set<uint_fast64_t> actionIndicesToDelete;
std::vector<Module> newModules;
std::vector<Constant> newConstants = this->getConstants();
for (auto const& module : this->getModules()) {
// Remove identity assignments from the updates
std::vector<Constant> newConstants = substitutedProgram.getConstants();
for (auto const& module : substitutedProgram.getModules()) {
// Discard all commands with a guard equivalent to false and remove identity assignments from the updates.
std::vector<Command> newCommands;
for (auto const& command : module.getCommands()) {
newCommands.emplace_back(command.removeIdentityAssignmentsFromUpdates());
if (!command.getGuardExpression().isFalse()) {
newCommands.emplace_back(command.removeIdentityAssignmentsFromUpdates());
}
}
// Substitute Variables by Global constants if possible.
// Substitute variables by global constants if possible.
std::map<storm::expressions::Variable, storm::expressions::Expression> booleanVars;
std::map<storm::expressions::Variable, storm::expressions::Expression> integerVars;
for (auto const& variable : module.getBooleanVariables()) {
@ -1171,54 +1249,84 @@ namespace storm {
integerVars.emplace(variable.getExpressionVariable(), variable.getInitialValueExpression());
}
// Collect all variables that are being written. These variables cannot be turned to constants.
for (auto const& command : newCommands) {
// Check all updates.
for (auto const& update : command.getUpdates()) {
// Check all assignments.
for (auto const& assignment : update.getAssignments()) {
auto bit = booleanVars.find(assignment.getVariable());
if(bit != booleanVars.end()) {
booleanVars.erase(bit);
if (assignment.getVariable().getType().isBooleanType()) {
auto it = booleanVars.find(assignment.getVariable());
if (it != booleanVars.end()) {
booleanVars.erase(it);
}
} else {
auto iit = integerVars.find(assignment.getVariable());
if(iit != integerVars.end()) {
integerVars.erase(iit);
auto it = integerVars.find(assignment.getVariable());
if (it != integerVars.end()) {
integerVars.erase(it);
}
}
}
}
}
std::vector<storm::prism::BooleanVariable> newBVars;
for(auto const& variable : module.getBooleanVariables()) {
if(booleanVars.count(variable.getExpressionVariable()) == 0) {
newBVars.push_back(variable);
std::vector<storm::prism::BooleanVariable> newBooleanVars;
for (auto const& variable : module.getBooleanVariables()) {
if (booleanVars.find(variable.getExpressionVariable()) == booleanVars.end()) {
newBooleanVars.push_back(variable);
}
}
std::vector<storm::prism::IntegerVariable> newIVars;
for(auto const& variable : module.getIntegerVariables()) {
if(integerVars.count(variable.getExpressionVariable()) == 0) {
newIVars.push_back(variable);
std::vector<storm::prism::IntegerVariable> newIntegerVars;
for (auto const& variable : module.getIntegerVariables()) {
if (integerVars.find(variable.getExpressionVariable()) == integerVars.end()) {
newIntegerVars.push_back(variable);
}
}
newModules.emplace_back(module.getName(), newBVars, newIVars, newCommands);
newModules.emplace_back(module.getName(), newBooleanVars, newIntegerVars, newCommands);
// Determine the set of action indices that have been deleted entirely.
std::set_difference(module.getSynchronizingActionIndices().begin(), module.getSynchronizingActionIndices().end(), newModules.back().getSynchronizingActionIndices().begin(), newModules.back().getSynchronizingActionIndices().end(), std::inserter(actionIndicesToDelete, actionIndicesToDelete.begin()));
for(auto const& entry : booleanVars) {
for (auto const& entry : booleanVars) {
newConstants.emplace_back(entry.first, entry.second);
}
for(auto const& entry : integerVars) {
for (auto const& entry : integerVars) {
newConstants.emplace_back(entry.first, entry.second);
}
}
return replaceModulesAndConstantsInProgram(newModules, newConstants).substituteConstants();
// If we have to delete whole actions, do so now.
std::map<std::string, uint_fast64_t> newActionToIndexMap;
std::vector<RewardModel> newRewardModels;
if (!actionIndicesToDelete.empty()) {
boost::container::flat_set<uint_fast64_t> actionsToKeep;
std::set_difference(this->getSynchronizingActionIndices().begin(), this->getSynchronizingActionIndices().end(), actionIndicesToDelete.begin(), actionIndicesToDelete.end(), std::inserter(actionsToKeep, actionsToKeep.begin()));
// Insert the silent action as this is not contained in the synchronizing action indices.
actionsToKeep.insert(0);
std::vector<Module> cleanedModules;
cleanedModules.reserve(newModules.size());
for (auto const& module : newModules) {
cleanedModules.emplace_back(module.restrictCommands(actionsToKeep));
}
newModules = std::move(cleanedModules);
newRewardModels.reserve(substitutedProgram.getNumberOfRewardModels());
for (auto const& rewardModel : substitutedProgram.getRewardModels()) {
newRewardModels.emplace_back(rewardModel.restrictActionRelatedRewards(actionsToKeep));
}
for (auto const& entry : this->getActionNameToIndexMapping()) {
if (actionsToKeep.find(entry.second) != actionsToKeep.end()) {
newActionToIndexMap.emplace(entry.first, entry.second);
}
}
}
}
Program Program::replaceModulesAndConstantsInProgram(std::vector<Module> const& newModules, std::vector<Constant> const& newConstants) {
return Program(this->manager, modelType, newConstants, getGlobalBooleanVariables(), getGlobalIntegerVariables(), getFormulas(), newModules, getActionNameToIndexMapping(), getRewardModels(), getLabels(), getInitialConstruct(), this->getOptionalSystemCompositionConstruct());
return Program(this->manager, modelType, newConstants, getGlobalBooleanVariables(), getGlobalIntegerVariables(), getFormulas(), newModules, actionIndicesToDelete.empty() ? getActionNameToIndexMapping() : newActionToIndexMap, actionIndicesToDelete.empty() ? this->getRewardModels() : newRewardModels, getLabels(), getOptionalInitialConstruct(), this->getOptionalSystemCompositionConstruct());
}
Program Program::flattenModules(std::unique_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory) const {
@ -1404,7 +1512,7 @@ namespace storm {
// Finally, we can create the module and the program and return it.
storm::prism::Module singleModule(newModuleName.str(), allBooleanVariables, allIntegerVariables, newCommands, this->getFilename(), 0);
return Program(manager, this->getModelType(), this->getConstants(), std::vector<storm::prism::BooleanVariable>(), std::vector<storm::prism::IntegerVariable>(), this->getFormulas(), {singleModule}, actionToIndexMap, this->getRewardModels(), this->getLabels(), this->getInitialConstruct(), this->getOptionalSystemCompositionConstruct(), this->getFilename(), 0, true);
return Program(manager, this->getModelType(), this->getConstants(), std::vector<storm::prism::BooleanVariable>(), std::vector<storm::prism::IntegerVariable>(), this->getFormulas(), {singleModule}, actionToIndexMap, this->getRewardModels(), this->getLabels(), this->getOptionalInitialConstruct(), this->getOptionalSystemCompositionConstruct(), this->getFilename(), 0, true);
}
std::unordered_map<uint_fast64_t, std::string> Program::buildCommandIndexToActionNameMap() const {
@ -1527,7 +1635,7 @@ namespace storm {
default: modelType = storm::jani::ModelType::UNDEFINED;
}
storm::jani::Model janiModel("jani_from_prism", modelType, 1, manager);
// Add all constants of the PRISM program to the JANI model.
for (auto const& constant : constants) {
janiModel.addConstant(storm::jani::Constant(constant.getName(), constant.getExpressionVariable(), constant.isDefined() ? boost::optional<storm::expressions::Expression>(constant.getExpression()) : boost::none));
@ -1539,12 +1647,22 @@ namespace storm {
// Add all global variables of the PRISM program to the JANI model.
for (auto const& variable : globalIntegerVariables) {
storm::jani::BoundedIntegerVariable const& newVariable = janiModel.addBoundedIntegerVariable(storm::jani::BoundedIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), variable.getLowerBoundExpression(), variable.getUpperBoundExpression()));
variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable);
if (variable.hasInitialValue()) {
storm::jani::BoundedIntegerVariable const& createdVariable = janiModel.addBoundedIntegerVariable(storm::jani::BoundedIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), false, variable.getLowerBoundExpression(), variable.getUpperBoundExpression()));
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
} else {
storm::jani::BoundedIntegerVariable const& createdVariable = janiModel.addBoundedIntegerVariable(storm::jani::BoundedIntegerVariable(variable.getName(), variable.getExpressionVariable(), false, variable.getLowerBoundExpression(), variable.getUpperBoundExpression()));
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
}
}
for (auto const& variable : globalBooleanVariables) {
storm::jani::BooleanVariable const& newVariable = janiModel.addBooleanVariable(storm::jani::BooleanVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression()));
variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable);
if (variable.hasInitialValue()) {
storm::jani::BooleanVariable const& createdVariable = janiModel.addBooleanVariable(storm::jani::BooleanVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), false));
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
} else {
storm::jani::BooleanVariable const& createdVariable = janiModel.addBooleanVariable(storm::jani::BooleanVariable(variable.getName(), variable.getExpressionVariable(), false));
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
}
}
// Add all actions of the PRISM program to the JANI model.
@ -1556,7 +1674,7 @@ namespace storm {
}
// Because of the rules of JANI, we have to make all variables of modules global that are read by other modules.
// Create a mapping from variables to the indices of module indices that write/read the variable.
std::map<storm::expressions::Variable, std::set<uint_fast64_t>> variablesToAccessingModuleIndices;
for (uint_fast64_t index = 0; index < modules.size(); ++index) {
@ -1584,31 +1702,30 @@ namespace storm {
// previously built mapping to make variables global that are read by more than one module.
for (auto const& module : modules) {
storm::jani::Automaton automaton(module.getName());
for (auto const& variable : module.getIntegerVariables()) {
storm::jani::BoundedIntegerVariable newIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), variable.getLowerBoundExpression(), variable.getUpperBoundExpression());
storm::jani::BoundedIntegerVariable newIntegerVariable = *storm::jani::makeBoundedIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.hasInitialValue() ? boost::make_optional(variable.getInitialValueExpression()) : boost::none, false, variable.getLowerBoundExpression(), variable.getUpperBoundExpression());
std::set<uint_fast64_t> const& accessingModuleIndices = variablesToAccessingModuleIndices[variable.getExpressionVariable()];
// If there is exactly one module reading and writing the variable, we can make the variable local to this module.
if (!allVariablesGlobal && accessingModuleIndices.size() == 1) {
storm::jani::BoundedIntegerVariable const& newVariable = automaton.addBoundedIntegerVariable(newIntegerVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable);
storm::jani::BoundedIntegerVariable const& createdVariable = automaton.addBoundedIntegerVariable(newIntegerVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
} else if (!accessingModuleIndices.empty()) {
// Otherwise, we need to make it global.
storm::jani::BoundedIntegerVariable const& newVariable = janiModel.addBoundedIntegerVariable(newIntegerVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable);
storm::jani::BoundedIntegerVariable const& createdVariable = janiModel.addBoundedIntegerVariable(newIntegerVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
}
}
for (auto const& variable : module.getBooleanVariables()) {
storm::jani::BooleanVariable newBooleanVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression());
storm::jani::BooleanVariable newBooleanVariable = *storm::jani::makeBooleanVariable(variable.getName(), variable.getExpressionVariable(), variable.hasInitialValue() ? boost::make_optional(variable.getInitialValueExpression()) : boost::none, false);
std::set<uint_fast64_t> const& accessingModuleIndices = variablesToAccessingModuleIndices[variable.getExpressionVariable()];
// If there is exactly one module reading and writing the variable, we can make the variable local to this module.
if (!allVariablesGlobal && accessingModuleIndices.size() == 1) {
storm::jani::BooleanVariable const& newVariable = automaton.addBooleanVariable(newBooleanVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable);
storm::jani::BooleanVariable const& createdVariable = automaton.addBooleanVariable(newBooleanVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
} else if (!accessingModuleIndices.empty()) {
// Otherwise, we need to make it global.
storm::jani::BooleanVariable const& newVariable = janiModel.addBooleanVariable(newBooleanVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable);
storm::jani::BooleanVariable const& createdVariable = janiModel.addBooleanVariable(newBooleanVariable);
variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
}
}
automaton.setInitialStatesRestriction(manager->boolean(true));
@ -1647,7 +1764,12 @@ namespace storm {
janiModel.addAutomaton(automaton);
}
janiModel.setInitialStatesRestriction(manager->boolean(true));
if (this->hasInitialConstruct()) {
janiModel.setInitialStatesRestriction(this->getInitialConstruct().getInitialStatesExpression());
} else {
janiModel.setInitialStatesRestriction(manager->boolean(true));
}
// Set the standard system composition. This is possible, because we reject non-standard compositions anyway.
if (this->specifiesSystemComposition()) {
@ -1662,6 +1784,19 @@ namespace storm {
return janiModel;
}
void Program::createMissingInitialValues() {
for (auto& variable : globalBooleanVariables) {
if (!variable.hasInitialValue()) {
variable.setInitialValueExpression(manager->boolean(false));
}
}
for (auto& variable : globalIntegerVariables) {
if (!variable.hasInitialValue()) {
variable.setInitialValueExpression(variable.getLowerBoundExpression());
}
}
}
std::ostream& operator<<(std::ostream& out, Program::ModelType const& type) {
switch (type) {
case Program::ModelType::UNDEFINED: out << "undefined"; break;
@ -1706,7 +1841,9 @@ namespace storm {
stream << label << std::endl;
}
stream << program.getInitialConstruct() << std::endl;
if (program.hasInitialConstruct()) {
stream << program.getInitialConstruct() << std::endl;
}
if (program.specifiesSystemComposition()) {
stream << program.getSystemCompositionConstruct();

36
src/storage/prism/Program.h

@ -175,7 +175,7 @@ namespace storm {
* @return The global boolean variables of the program.
*/
std::vector<BooleanVariable> const& getGlobalBooleanVariables() const;
/*!
* Retrieves a the global boolean variable with the given name.
*
@ -285,12 +285,31 @@ namespace storm {
*/
std::map<std::string, uint_fast64_t> const& getActionNameToIndexMapping() const;
/*!
* Retrieves whether the program specifies an initial construct.
*/
bool hasInitialConstruct() const;
/*!
* Retrieves the initial construct of the program.
*
* @return The initial construct of the program.
*/
InitialConstruct const& getInitialConstruct() const;
/*!
* Retrieves an optional containing the initial construct of the program if there is any and nothing otherwise.
*
* @return The initial construct of the program.
*/
boost::optional<InitialConstruct> const& getOptionalInitialConstruct() const;
/*!
* Retrieves an expression characterizing the initial states.
*
* @return an expression characterizing the initial states.
*/
storm::expressions::Expression getInitialStatesExpression() const;
/*!
* Retrieves whether the program specifies a system composition in terms of process algebra operations over
@ -587,6 +606,11 @@ namespace storm {
*/
Command synchronizeCommands(uint_fast64_t newCommandIndex, uint_fast64_t actionIndex, uint_fast64_t firstUpdateIndex, std::string const& actionName, std::vector<std::reference_wrapper<Command const>> const& commands) const;
/*!
* Equips all global variables without initial values with initial values based on their type.
*/
void createMissingInitialValues();
// The manager responsible for the variables/expressions of the program.
std::shared_ptr<storm::expressions::ExpressionManager> manager;
@ -633,7 +657,7 @@ namespace storm {
std::map<std::string, uint_fast64_t> rewardModelToIndexMap;
// The initial construct of the program.
InitialConstruct initialConstruct;
boost::optional<InitialConstruct> initialConstruct;
// If set, this specifies the way the modules are composed to obtain the full system.
boost::optional<SystemCompositionConstruct> systemCompositionConstruct;
@ -661,14 +685,6 @@ namespace storm {
// A mapping from variable names to the modules in which they were declared.
std::map<std::string, uint_fast64_t> variableToModuleIndexMap;
/**
* Takes the current program and replaces all modules. As we reuse the expression manager, we recommend to not use the original program any further.
* @param newModules the modules which replace the old modules.
* @param newConstants the constants which replace the old constants.
* @return A program with the new modules and constants.
*/
Program replaceModulesAndConstantsInProgram(std::vector<Module> const& newModules, std::vector<Constant> const& newConstants);
};
std::ostream& operator<<(std::ostream& out, Program::ModelType const& type);

18
src/storage/prism/RewardModel.cpp

@ -81,6 +81,24 @@ namespace storm {
return true;
}
RewardModel RewardModel::restrictActionRelatedRewards(boost::container::flat_set<uint_fast64_t> const& actionIndicesToKeep) const {
std::vector<StateActionReward> newStateActionRewards;
for (auto const& stateActionReward : this->getStateActionRewards()) {
if (actionIndicesToKeep.find(stateActionReward.getActionIndex()) != actionIndicesToKeep.end()) {
newStateActionRewards.emplace_back(stateActionReward);
}
}
std::vector<TransitionReward> newTransitionRewards;
for (auto const& transitionReward : this->getTransitionRewards()) {
if (actionIndicesToKeep.find(transitionReward.getActionIndex()) != actionIndicesToKeep.end()) {
newTransitionRewards.emplace_back(transitionReward);
}
}
return RewardModel(this->getName(), this->getStateRewards(), newStateActionRewards, newTransitionRewards, this->getFilename(), this->getLineNumber());
}
std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel) {
stream << "rewards";
if (rewardModel.getName() != "") {

9
src/storage/prism/RewardModel.h

@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include <map>
#include <boost/container/flat_set.hpp>
#include "src/storage/prism/StateReward.h"
#include "src/storage/prism/StateActionReward.h"
@ -108,6 +109,14 @@ namespace storm {
*/
bool containsVariablesOnlyInRewardValueExpressions(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const;
/*!
* Restricts all action-related rewards of the reward model to the ones with an action index in the provided set.
*
* @param actionIndicesToKeep The set of action indices to keep.
* @return The resulting reward model.
*/
RewardModel restrictActionRelatedRewards(boost::container::flat_set<uint_fast64_t> const& actionIndicesToKeep) const;
friend std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel);
private:

12
src/storage/prism/Variable.cpp

@ -5,11 +5,11 @@
namespace storm {
namespace prism {
Variable::Variable(storm::expressions::Variable const& variable, storm::expressions::Expression const& initialValueExpression, bool defaultInitialValue, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), variable(variable), initialValueExpression(initialValueExpression), defaultInitialValue(defaultInitialValue) {
Variable::Variable(storm::expressions::Variable const& variable, storm::expressions::Expression const& initialValueExpression, bool defaultInitialValue, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), variable(variable), initialValueExpression(initialValueExpression) {
// Nothing to do here.
}
Variable::Variable(storm::expressions::ExpressionManager& manager, Variable const& oldVariable, std::string const& newName, std::map<storm::expressions::Variable, storm::expressions::Expression> const& renaming, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), variable(manager.declareVariable(newName, oldVariable.variable.getType())), initialValueExpression(oldVariable.getInitialValueExpression().substitute(renaming)), defaultInitialValue(oldVariable.hasDefaultInitialValue()) {
Variable::Variable(storm::expressions::ExpressionManager& manager, Variable const& oldVariable, std::string const& newName, std::map<storm::expressions::Variable, storm::expressions::Expression> const& renaming, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), variable(manager.declareVariable(newName, oldVariable.variable.getType())), initialValueExpression(oldVariable.getInitialValueExpression().substitute(renaming)) {
// Intentionally left empty.
}
@ -17,14 +17,18 @@ namespace storm {
return this->variable.getName();
}
bool Variable::hasDefaultInitialValue() const {
return this->defaultInitialValue;
bool Variable::hasInitialValue() const {
return this->initialValueExpression.isInitialized();
}
storm::expressions::Expression const& Variable::getInitialValueExpression() const {
return this->initialValueExpression;
}
void Variable::setInitialValueExpression(storm::expressions::Expression const& initialValueExpression) {
this->initialValueExpression = initialValueExpression;
}
storm::expressions::Variable const& Variable::getExpressionVariable() const {
return this->variable;
}

27
src/storage/prism/Variable.h

@ -28,19 +28,27 @@ namespace storm {
std::string const& getName() const;
/*!
* Retrieves the expression defining the initial value of the variable.
* Retrieves whether the variable has an initial value.
*
* @return True iff the variable has an initial value.
*/
bool hasInitialValue() const;
/*!
* Retrieves the expression defining the initial value of the variable. This can only be called if there is
* an initial value (expression).
*
* @return The expression defining the initial value of the variable.
*/
storm::expressions::Expression const& getInitialValueExpression() const;
/*!
* Retrieves whether the variable has the default initial value with respect to its type.
* Sets the expression defining the initial value of the variable.
*
* @return True iff the variable has the default initial value.
* @param initialValueExpression The expression defining the initial value of the variable.
*/
bool hasDefaultInitialValue() const;
void setInitialValueExpression(storm::expressions::Expression const& initialValueExpression);
/*!
* Retrieves the expression variable associated with this variable.
*
@ -55,6 +63,10 @@ namespace storm {
*/
storm::expressions::Expression getExpression() const;
/*!
* Equips the variable with an initial value based on its type if not initial value is present.
*/
virtual void createMissingInitialValue() = 0;
// Make the constructors protected to forbid instantiation of this class.
protected:
@ -90,9 +102,6 @@ namespace storm {
// The constant expression defining the initial value of the variable.
storm::expressions::Expression initialValueExpression;
// A flag that stores whether the variable has its default initial expression.
bool defaultInitialValue;
};
} // namespace prism

13
src/storm.cpp

@ -6,6 +6,7 @@
#include "src/utility/initialize.h"
#include "src/settings/SettingsManager.h"
#include "src/settings/modules/GeneralSettings.h"
/*!
* Main entry point of the executable storm.
@ -13,7 +14,7 @@
int main(const int argc, const char** argv) {
try {
auto starttime = std::chrono::high_resolution_clock::now();
auto start = std::chrono::high_resolution_clock::now();
storm::utility::setUp();
storm::cli::printHeader("Storm", argc, argv);
storm::settings::initializeAll("Storm", "storm");
@ -27,11 +28,11 @@ int main(const int argc, const char** argv) {
// All operations have now been performed, so we clean up everything and terminate.
storm::utility::cleanUp();
auto endtime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endtime-starttime);
auto durationSec = std::chrono::duration_cast<std::chrono::seconds>(endtime-starttime);
if(storm::settings::getModule<storm::settings::modules::IOSettings>().isPrintTimingsSet()) {
std::cout << "Overal runtime: " << duration.count() << " ms. ( approx " << durationSec.count() << " seconds)." << std::endl;
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
auto durationSec = std::chrono::duration_cast<std::chrono::seconds>(end - start);
if(storm::settings::getModule<storm::settings::modules::GeneralSettings>().isPrintTimingsSet()) {
std::cout << "Overal runtime: " << duration.count() << " ms. (approximately " << durationSec.count() << " seconds)." << std::endl;
}
return 0;
} catch (storm::exceptions::BaseException const& exception) {

72
src/utility/constants.cpp

@ -39,6 +39,23 @@ namespace storm {
bool isConstant(ValueType const& a) {
return true;
}
template<typename ValueType>
bool isInteger(ValueType const& number) {
ValueType iPart;
ValueType result = std::modf(number, &iPart);
return result = zero<ValueType>();
}
template<>
bool isInteger(int const& number) {
return true;
}
template<>
bool isInteger(uint_fast64_t const& number) {
return true;
}
#ifdef STORM_HAVE_CARL
template<>
@ -50,7 +67,6 @@ namespace storm {
bool isZero(storm::RationalNumber const& a) {
return carl::isZero(a);
}
template<>
bool isOne(storm::RationalFunction const& a) {
@ -93,6 +109,16 @@ namespace storm {
// FIXME: this should be treated more properly.
return storm::RationalNumber(-1);
}
template<>
bool isInteger(storm::RationalNumber const& number) {
return carl::isInteger(number);
}
template<>
bool isInteger(storm::RationalFunction const& func) {
return storm::utility::isConstant(func) && storm::utility::isOne(func.denominator());
}
#endif
template<typename ValueType>
@ -102,9 +128,9 @@ namespace storm {
template<typename ValueType>
ValueType simplify(ValueType value) {
// In the general case, we don't do anything here, but merely return the value. If something else is
// supposed to happen here, the templated function can be specialized for this particular type.
return value;
// In the general case, we don't do anything here, but merely return the value. If something else is
// supposed to happen here, the templated function can be specialized for this particular type.
return value;
}
template<>
@ -151,7 +177,12 @@ namespace storm {
double convertNumber(RationalNumber const& number){
return carl::toDouble(number);
}
template<>
uint_fast64_t convertNumber(RationalNumber const& number){
return carl::toInt<unsigned long>(number);
}
template<>
RationalNumber convertNumber(double const& number){
return carl::rationalize<RationalNumber>(number);
@ -167,15 +198,31 @@ namespace storm {
return RationalFunction(carl::rationalize<RationalNumber>(number));
}
template<>
RationalNumber convertNumber(std::string const& number) {
return carl::rationalize<RationalNumber>(number);
}
template<>
RationalFunction convertNumber(RationalNumber const& number) {
return RationalFunction(number);
}
template<>
storm::RationalNumber abs(storm::RationalNumber const& number) {
uint_fast64_t convertNumber(RationalFunction const& func) {
return carl::toInt<unsigned long>(func.nominatorAsNumber());
}
template<>
RationalNumber abs(storm::RationalNumber const& number) {
return carl::abs(number);
}
template<>
RationalNumber pow(RationalNumber const& value, uint_fast64_t exponent) {
return carl::pow(value, exponent);
}
#endif
template<typename IndexType, typename ValueType>
@ -214,6 +261,7 @@ namespace storm {
template storm::storage::MatrixEntry<storm::storage::sparse::state_type, double>&& simplify(storm::storage::MatrixEntry<storm::storage::sparse::state_type, double>&& matrixEntry);
template double abs(double const& number);
template bool isInteger(double const& number);
template bool isOne(float const& value);
template bool isZero(float const& value);
@ -224,6 +272,7 @@ namespace storm {
template float infinity();
template float pow(float const& value, uint_fast64_t exponent);
template bool isInteger(float const& number);
template float simplify(float value);
@ -240,7 +289,8 @@ namespace storm {
template int infinity();
template int pow(int const& value, uint_fast64_t exponent);
template bool isInteger(int const& number);
template int simplify(int value);
template storm::storage::MatrixEntry<storm::storage::sparse::state_type, int> simplify(storm::storage::MatrixEntry<storm::storage::sparse::state_type, int> matrixEntry);
@ -278,12 +328,14 @@ namespace storm {
template storm::RationalNumber infinity();
template double convertNumber(storm::RationalNumber const& number);
template uint_fast64_t convertNumber(storm::RationalNumber const& number);
template storm::RationalNumber convertNumber(double const& number);
template storm::RationalNumber convertNumber(storm::RationalNumber const& number);
RationalNumber convertNumber(std::string const& number);
template storm::RationalNumber abs(storm::RationalNumber const& number);
// template storm::RationalNumber pow(storm::RationalNumber const& value, uint_fast64_t exponent);
template storm::RationalNumber pow(storm::RationalNumber const& value, uint_fast64_t exponent);
template storm::RationalNumber simplify(storm::RationalNumber value);
template storm::storage::MatrixEntry<storm::storage::sparse::state_type, storm::RationalNumber> simplify(storm::storage::MatrixEntry<storm::storage::sparse::state_type, storm::RationalNumber> matrixEntry);

3
src/utility/constants.h

@ -56,6 +56,9 @@ namespace storm {
template<typename ValueType>
ValueType abs(ValueType const& number);
template<typename ValueType>
bool isInteger(ValueType const& number);
}
}

2
src/utility/storm.cpp

@ -10,7 +10,7 @@
namespace storm {
storm::prism::Program parseProgram(std::string const& path) {
storm::prism::Program program= storm::parser::PrismParser::parse(path).simplify().simplify();
storm::prism::Program program = storm::parser::PrismParser::parse(path).simplify().simplify();
program.checkValidity();
return program;
}

4
src/utility/storm.h

@ -382,10 +382,10 @@ namespace storm {
if (model->getType() == storm::models::ModelType::Dtmc) {
result = verifySparseDtmc(model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(), task);
} else if (model->getType() == storm::models::ModelType::Mdp) {
std::shared_ptr<storm::models::sparse::Mdp<storm::RationalFunction>> mdp = model->template as<storm::models::sparse::Mdp<storm::RationalFunction>>();
//std::shared_ptr<storm::models::sparse::Mdp<storm::RationalFunction>> mdp = model->template as<storm::models::sparse::Mdp<storm::RationalFunction>>();
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support MDPs.");
} else if (model->getType() == storm::models::ModelType::Ctmc) {
verifySparseCtmc(model->template as<storm::models::sparse::Ctmc<storm::RationalFunction>>(), task);
result = verifySparseCtmc(model->template as<storm::models::sparse::Ctmc<storm::RationalFunction>>(), task);
} else {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support " << model->getType());
}

4
test/functional/parser/PrismParserTest.cpp

@ -79,10 +79,6 @@ TEST(PrismParser, ComplexTest) {
module mod3 = mod1 [ i = i1, j = j1, k = k1 ] endmodule
label "mal" = max(a, 10) > 0;
init
true
endinit
rewards "testrewards"
[a] true : a + 7;

10
util/osx-package/package.sh

@ -0,0 +1,10 @@
#!/bin/sh
DYLIBBUNDLER_DIR=/Users/chris/work/macdylibbundler/
mkdir -p $1
mkdir -p $1/bin
mkdir -p $1/lib
cp $2 $1/bin
$DYLIBBUNDLER_DIR/dylibbundler -cd -od -b -p @executable_path/../lib -x $1/bin/storm -d $1/lib
python packager.py --bin storm --dir $1

103
util/osx-package/packager.py

@ -0,0 +1,103 @@
import argparse
import subprocess
import os
from shutil import copyfile
def get_dependencies(file):
# Call otool -L file to obtain the dependencies.
proc = subprocess.Popen(["otool", "-L", args.binary], stdout=subprocess.PIPE)
result = {}
for line_bytes in proc.stdout:
line = line_bytes.decode("utf-8").strip()
lib = line.split()[0]
if (lib.startswith("@")):
lib = lib.split("/", 1)[1]
(base, file) = os.path.split(lib)
print(base + " // " + file)
return result
def create_package(args):
create_package_dirs(args.dir)
copy_binary_to_package_dir(args.bin, args.binary_basename, args.dir)
run_dylibbundler(args.bundler_binary, args.dir, args.binary_basename)
pass
def parse_arguments():
parser = argparse.ArgumentParser(description='Package the storm binary on Mac OS.')
parser.add_argument('--bin', dest='bin', help='the binary to package', default='storm')
parser.add_argument('--dir', dest='dir', help='the root directory of the package (will be created if it does not exist)', default='.')
parser.add_argument('--dylibbundler', dest='bundler_binary', help='the binary of the dylibbundler', default='dylibbundler')
args = parser.parse_args()
args.binary_dir = os.path.split(args.bin)[0]
args.binary_basename = os.path.split(args.bin)[1]
return args
def create_package_dirs(root_dir):
if not os.path.exists(root_dir):
os.makedirs(root_dir)
if not os.path.exists(root_dir + "/bin"):
os.makedirs(root_dir + "/bin")
if not os.path.exists(root_dir + "/lib"):
os.makedirs(root_dir + "/bin")
pass
def copy_binary_to_package_dir(binary, binary_basename, root_dir):
copyfile(binary, root_dir + "/bin/storm")
pass
def run_dylibbundler(bundler_binary, root_dir, binary_basename):
command = [bundler_binary, "-cd", "-od", "-b", "-p", "@executable_path/../lib", "-x", root_dir + "/bin/" + binary_basename, "-d", root_dir + "/lib"]
print("executing " + str(command))
#proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
pass
def fix_paths(root_dir, binary_basename):
fix_paths_file(root_dir + "/bin/" + binary_basename)
for file in os.listdir(root_dir + "/lib"):
fix_paths_file(root_dir + "/lib/" + file)
pass
pass
def fix_paths_file(file):
print("fixing paths for " + file)
fixable_deps = get_fixable_deps(file)
for (path, lib) in fixable_deps:
change_fixable_dep(file, path, lib)
native_libs = ["libc++.1.dylib", "libSystem.B.dylib"]
def get_fixable_deps(file):
# Call otool -L file to obtain the dependencies.
proc = subprocess.Popen(["otool", "-L", file], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
result = []
for line_bytes in proc.stdout:
line = line_bytes.decode("utf-8").strip()
lib = line.split()[0]
if lib.startswith("@rpath/"):
result.append(("@rpath", lib.split("/", 1)[1]))
elif lib.startswith("/"):
path_file = os.path.split(lib)
if path_file[1] not in native_libs:
result.append((path_file[0], path_file[1]))
return result
def change_fixable_dep(file, path, lib):
# Call install_name_tool to change the fixable dependencies
command = ["install_name_tool", "-change", path + "/" + lib, "@executable_path/../lib/" + lib, file]
print("executing " + str(command))
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
#print ("after call to install_name_tool")
#proc = subprocess.Popen(["otool", "-L", file], stdout=subprocess.PIPE)
#for line_bytes in proc.stdout:
# line = line_bytes.decode("utf-8").strip()
# print(line)
pass
if __name__ == "__main__":
args = parse_arguments()
#create_package(args)
fix_paths(args.dir, args.binary_basename)
|||||||
100:0
Loading…
Cancel
Save