diff --git a/CMakeLists.txt b/CMakeLists.txt index e8b342aed..4af9a135b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,10 +258,9 @@ file(GLOB_RECURSE STORM_SETTINGS_FILES ${PROJECT_SOURCE_DIR}/src/settings/*.h ${ file(GLOB_RECURSE STORM_SOLVER_FILES ${PROJECT_SOURCE_DIR}/src/solver/*.h ${PROJECT_SOURCE_DIR}/src/solver/*.cpp) file(GLOB STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp) file(GLOB_RECURSE STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/*.cpp) +file(GLOB_RECURSE STORM_STORAGE_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.h ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.cpp) +file(GLOB_RECURSE STORM_STORAGE_PRISM_FILES ${PROJECT_SOURCE_DIR}/src/storage/prism/*.h ${PROJECT_SOURCE_DIR}/src/storage/prism/*.cpp) file(GLOB_RECURSE STORM_UTILITY_FILES ${PROJECT_SOURCE_DIR}/src/utility/*.h ${PROJECT_SOURCE_DIR}/src/utility/*.cpp) -file(GLOB STORM_IR_FILES ${PROJECT_SOURCE_DIR}/src/ir/*.h ${PROJECT_SOURCE_DIR}/src/ir/*.cpp) -file(GLOB_RECURSE STORM_IR_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/ir/expressions/*.h ${PROJECT_SOURCE_DIR}/src/ir/expressions/*.cpp) - # Test Sources # Note that the tests also need the source files, except for the main file file(GLOB_RECURSE STORM_FUNCTIONAL_TEST_FILES ${STORM_CPP_TESTS_BASE_PATH}/functional/*.h ${STORM_CPP_TESTS_BASE_PATH}/functional/*.cpp) @@ -280,8 +279,6 @@ source_group(formula\\csl FILES ${STORM_FORMULA_CSL_FILES}) source_group(formula\\ltl FILES ${STORM_FORMULA_LTL_FILES}) source_group(formula\\prctl FILES ${STORM_FORMULA_PRCTL_FILES}) source_group(generated FILES ${STORM_BUILD_HEADERS}) -source_group(ir FILES ${STORM_IR_FILES}) -source_group(ir\\expressions FILES ${STORM_IR_EXPRESSIONS_FILES}) source_group(modelchecker FILES ${STORM_MODELCHECKER_FILES}) source_group(counterexamples FILES ${STORM_COUNTEREXAMPLES_FILES}) source_group(models FILES ${STORM_MODELS_FILES}) @@ -291,6 +288,8 @@ source_group(settings FILES ${STORM_SETTINGS_FILES}) source_group(solver FILES ${STORM_SOLVER_FILES}) source_group(storage FILES ${STORM_STORAGE_FILES}) source_group(storage\\dd FILES ${STORM_STORAGE_DD_FILES}) +source_group(storage\\expressions FILES ${STORM_STORAGE_EXPRESSIONS_FILES}) +source_group(storage\\prism FILES ${STORM_STORAGE_PRISM_FILES}) source_group(utility FILES ${STORM_UTILITY_FILES}) source_group(functional-test FILES ${STORM_FUNCTIONAL_TEST_FILES}) source_group(performance-test FILES ${STORM_PERFORMANCE_TEST_FILES}) diff --git a/examples/dtmc/synchronous_leader/leader4_8.pm b/examples/dtmc/synchronous_leader/leader4_8.pm index fc8f167a0..188039cf3 100644 --- a/examples/dtmc/synchronous_leader/leader4_8.pm +++ b/examples/dtmc/synchronous_leader/leader4_8.pm @@ -4,8 +4,8 @@ dtmc // CONSTANTS -const N = 4; // number of processes -const K = 8; // range of probabilistic choice +const int N = 4; // number of processes +const int K = 8; // range of probabilistic choice // counter module used to count the number of processes that have been read // and to know when a process has decided diff --git a/examples/dtmc/synchronous_leader/leader5_8.pm b/examples/dtmc/synchronous_leader/leader5_8.pm index 72139fda9..4723ed5b0 100644 --- a/examples/dtmc/synchronous_leader/leader5_8.pm +++ b/examples/dtmc/synchronous_leader/leader5_8.pm @@ -4,8 +4,8 @@ dtmc // CONSTANTS -const N = 5; // number of processes -const K = 8; // range of probabilistic choice +const int N = 5; // number of processes +const int K = 8; // range of probabilistic choice // counter module used to count the number of processes that have been read // and to know when a process has decided diff --git a/examples/dtmc/synchronous_leader/leader6_8.pm b/examples/dtmc/synchronous_leader/leader6_8.pm index 283042ad5..a31773b1d 100644 --- a/examples/dtmc/synchronous_leader/leader6_8.pm +++ b/examples/dtmc/synchronous_leader/leader6_8.pm @@ -4,8 +4,8 @@ dtmc // CONSTANTS -const N = 6; // number of processes -const K = 8; // range of probabilistic choice +const int N = 6; // number of processes +const int K = 8; // range of probabilistic choice // counter module used to count the number of processes that have been read // and to know when a process has decided diff --git a/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h b/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h index 8e3686170..5a2c2f952 100644 --- a/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h +++ b/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h @@ -767,6 +767,8 @@ extern int Cudd_bddVarIsBound (DdManager *dd, int index); extern DdNode * Cudd_addExistAbstract (DdManager *manager, DdNode *f, DdNode *cube); extern DdNode * Cudd_addUnivAbstract (DdManager *manager, DdNode *f, DdNode *cube); extern DdNode * Cudd_addOrAbstract (DdManager *manager, DdNode *f, DdNode *cube); +extern DdNode * Cudd_addMinAbstract(DdManager * manager, DdNode * f, DdNode * cube); +extern DdNode * Cudd_addMaxAbstract(DdManager * manager, DdNode * f, DdNode * cube); extern DdNode * Cudd_addApply (DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g); extern DdNode * Cudd_addPlus (DdManager *dd, DdNode **f, DdNode **g); extern DdNode * Cudd_addTimes (DdManager *dd, DdNode **f, DdNode **g); diff --git a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c index 5e809c134..7d774586c 100644 --- a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c +++ b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c @@ -11,12 +11,16 @@ <li> Cudd_addExistAbstract() <li> Cudd_addUnivAbstract() <li> Cudd_addOrAbstract() + <li> Cudd_addMinAbstract() + <li> Cudd_addMaxAbstract() </ul> Internal procedures included in this module: <ul> <li> cuddAddExistAbstractRecur() <li> cuddAddUnivAbstractRecur() <li> cuddAddOrAbstractRecur() + <li> cuddAddMinAbstractRecur() + <li> cuddAddMaxAbstractRecur() </ul> Static procedures included in this module: <ul> @@ -229,6 +233,82 @@ Cudd_addOrAbstract( } /* end of Cudd_addOrAbstract */ +/**Function******************************************************************** + + Synopsis [Abstracts all the variables in cube from the + ADD f by taking the minimum.] + + Description [Abstracts all the variables in cube from the ADD f + by taking the minimum over all possible values taken by the + variables. Returns the abstracted ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract] + + Note: Added by Dave Parker 14/6/99 + + ******************************************************************************/ +DdNode * +Cudd_addMinAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *res; + + if (addCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err,"Error: Can only abstract cubes"); + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddAddMinAbstractRecur(manager, f, cube); + } while (manager->reordered == 1); + return(res); + +} /* end of Cudd_addMinAbstract */ + + +/**Function******************************************************************** + + Synopsis [Abstracts all the variables in cube from the + ADD f by taking the maximum.] + + Description [Abstracts all the variables in cube from the ADD f + by taking the maximum over all possible values taken by the + variables. Returns the abstracted ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract] + + Note: Added by Dave Parker 14/6/99 + + ******************************************************************************/ +DdNode * +Cudd_addMaxAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *res; + + if (addCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err,"Error: Can only abstract cubes"); + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddAddMaxAbstractRecur(manager, f, cube); + } while (manager->reordered == 1); + return(res); + +} /* end of Cudd_addMaxAbstract */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ @@ -542,7 +622,188 @@ cuddAddOrAbstractRecur( } /* end of cuddAddOrAbstractRecur */ +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addMinAbstract.] + + Description [Performs the recursive step of Cudd_addMinAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + + ******************************************************************************/ +DdNode * +cuddAddMinAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *T, *E, *res, *res1, *res2, *zero; + + zero = DD_ZERO(manager); + + /* Cube is guaranteed to be a cube at this point. */ + if (f == zero || cuddIsConstant(cube)) { + return(f); + } + + /* Abstract a variable that does not appear in f. */ + if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { + res = cuddAddMinAbstractRecur(manager, f, cuddT(cube)); + return(res); + } + + if ((res = cuddCacheLookup2(manager, Cudd_addMinAbstract, f, cube)) != NULL) { + return(res); + } + + + T = cuddT(f); + E = cuddE(f); + + /* If the two indices are the same, so are their levels. */ + if (f->index == cube->index) { + res1 = cuddAddMinAbstractRecur(manager, T, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddMinAbstractRecur(manager, E, cuddT(cube)); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = cuddAddApplyRecur(manager, Cudd_addMinimum, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + cuddCacheInsert2(manager, Cudd_addMinAbstract, f, cube, res); + cuddDeref(res); + return(res); + } + else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ + res1 = cuddAddMinAbstractRecur(manager, T, cube); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddMinAbstractRecur(manager, E, cube); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = (res1 == res2) ? res1 : + cuddUniqueInter(manager, (int) f->index, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + cuddCacheInsert2(manager, Cudd_addMinAbstract, f, cube, res); + return(res); + } + +} /* end of cuddAddMinAbstractRecur */ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addMaxAbstract.] + + Description [Performs the recursive step of Cudd_addMaxAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + + ******************************************************************************/ +DdNode * +cuddAddMaxAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *T, *E, *res, *res1, *res2, *zero; + + zero = DD_ZERO(manager); + + /* Cube is guaranteed to be a cube at this point. */ + if (f == zero || cuddIsConstant(cube)) { + return(f); + } + + /* Abstract a variable that does not appear in f. */ + if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { + res = cuddAddMaxAbstractRecur(manager, f, cuddT(cube)); + return(res); + } + + if ((res = cuddCacheLookup2(manager, Cudd_addMaxAbstract, f, cube)) != NULL) { + return(res); + } + + + T = cuddT(f); + E = cuddE(f); + + /* If the two indices are the same, so are their levels. */ + if (f->index == cube->index) { + res1 = cuddAddMaxAbstractRecur(manager, T, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddMaxAbstractRecur(manager, E, cuddT(cube)); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = cuddAddApplyRecur(manager, Cudd_addMaximum, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + cuddCacheInsert2(manager, Cudd_addMaxAbstract, f, cube, res); + cuddDeref(res); + return(res); + } + else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ + res1 = cuddAddMaxAbstractRecur(manager, T, cube); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddMaxAbstractRecur(manager, E, cube); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = (res1 == res2) ? res1 : + cuddUniqueInter(manager, (int) f->index, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + cuddCacheInsert2(manager, Cudd_addMaxAbstract, f, cube, res); + return(res); + } + +} /* end of cuddAddMaxAbstractRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ diff --git a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h index 398b057f7..313a56586 100644 --- a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h +++ b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h @@ -1000,6 +1000,8 @@ dd->nextSample += 250000;} extern DdNode * cuddAddExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube); extern DdNode * cuddAddUnivAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube); extern DdNode * cuddAddOrAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube); +extern DdNode * cuddAddMinAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube); +extern DdNode * cuddAddMaxAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube); extern DdNode * cuddAddApplyRecur (DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g); extern DdNode * cuddAddMonadicApplyRecur (DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f); extern DdNode * cuddAddScalarInverseRecur (DdManager *dd, DdNode *f, DdNode *epsilon); diff --git a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc index ffbaaf826..c9fcf7b11 100644 --- a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc +++ b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc @@ -2405,6 +2405,23 @@ ADD::OrAbstract( } // ADD::OrAbstract +ADD +ADD::MinAbstract(const ADD& cube) const +{ + DdManager *mgr = checkSameManager(cube); + DdNode *result = Cudd_addMinAbstract(mgr, node, cube.node); + checkReturnValue(result); + return ADD(p, result); +} // ADD::MinAbstract + +ADD +ADD::MaxAbstract(const ADD& cube) const +{ + DdManager *mgr = checkSameManager(cube); + DdNode *result = Cudd_addMaxAbstract(mgr, node, cube.node); + checkReturnValue(result); + return ADD(p, result); +} // ADD::MaxAbstract ADD ADD::Plus( diff --git a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh index 0dce65989..a1a859490 100644 --- a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh +++ b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh @@ -373,6 +373,8 @@ public: ADD ExistAbstract(const ADD& cube) const; ADD UnivAbstract(const ADD& cube) const; ADD OrAbstract(const ADD& cube) const; + ADD MinAbstract(const ADD& cube) const; + ADD MaxAbstract(const ADD& cube) const; ADD Plus(const ADD& g) const; ADD Times(const ADD& g) const; ADD Threshold(const ADD& g) const; diff --git a/src/adapters/ExplicitModelAdapter.h b/src/adapters/ExplicitModelAdapter.h index f1ef50396..777807c06 100644 --- a/src/adapters/ExplicitModelAdapter.h +++ b/src/adapters/ExplicitModelAdapter.h @@ -15,12 +15,11 @@ #include <queue> #include <boost/functional/hash.hpp> #include <boost/container/flat_set.hpp> +#include <boost/algorithm/string.hpp> -#include "src/ir/Program.h" -#include "src/ir/RewardModel.h" -#include "src/ir/StateReward.h" -#include "src/ir/TransitionReward.h" -#include "src/utility/IRUtility.h" +#include "src/storage/prism/Program.h" +#include "src/storage/expressions/SimpleValuation.h" +#include "src/utility/PrismUtility.h" #include "src/models/AbstractModel.h" #include "src/models/Dtmc.h" #include "src/models/Ctmc.h" @@ -29,20 +28,22 @@ #include "src/models/AtomicPropositionsLabeling.h" #include "src/storage/SparseMatrix.h" #include "src/settings/Settings.h" +#include "src/exceptions/ExceptionMacros.h" #include "src/exceptions/WrongFormatException.h" -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" -extern log4cplus::Logger logger; - -using namespace storm::utility::ir; - namespace storm { namespace adapters { + + using namespace storm::utility::prism; template<typename ValueType> class ExplicitModelAdapter { public: + typedef storm::expressions::SimpleValuation StateType; + typedef storm::expressions::SimpleValuationPointerHash StateHash; + typedef storm::expressions::SimpleValuationPointerCompare StateCompare; + typedef storm::expressions::SimpleValuationPointerLess StateLess; + // A structure holding information about the reachable state space. struct StateInformation { StateInformation() : reachableStates(), stateToIndexMap() { @@ -52,10 +53,19 @@ namespace storm { // A list of reachable states. std::vector<StateType*> reachableStates; + // A list of initial states. + std::vector<uint_fast64_t> initialStateIndices; + // A mapping from states to indices in the list of reachable states. std::unordered_map<StateType*, uint_fast64_t, StateHash, StateCompare> stateToIndexMap; }; + // A structure storing information about the used variables of the program. + struct VariableInformation { + // A mapping of (integer) variable to their lower/upper bounds. + std::map<std::string, std::pair<int_fast64_t, int_fast64_t>> variableToBoundsMap; + }; + // A structure holding the individual components of a model. struct ModelComponents { ModelComponents() : transitionMatrix(), stateLabeling(), stateRewards(), transitionRewardMatrix(), choiceLabeling() { @@ -78,6 +88,62 @@ namespace storm { std::vector<boost::container::flat_set<uint_fast64_t>> choiceLabeling; }; + static std::map<std::string, storm::expressions::Expression> parseConstantDefinitionString(storm::prism::Program const& program, std::string const& constantDefinitionString) { + std::map<std::string, storm::expressions::Expression> constantDefinitions; + std::set<std::string> definedConstants; + + if (!constantDefinitionString.empty()) { + // Parse the string that defines the undefined constants of the model and make sure that it contains exactly + // one value for each undefined constant of the model. + std::vector<std::string> definitions; + boost::split(definitions, constantDefinitionString, boost::is_any_of(",")); + for (auto& definition : definitions) { + boost::trim(definition); + + // Check whether the token could be a legal constant definition. + uint_fast64_t positionOfAssignmentOperator = definition.find('='); + if (positionOfAssignmentOperator == std::string::npos) { + throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: syntax error."; + } + + // Now extract the variable name and the value from the string. + std::string constantName = definition.substr(0, positionOfAssignmentOperator); + boost::trim(constantName); + std::string value = definition.substr(positionOfAssignmentOperator + 1); + boost::trim(value); + + // Check whether the constant is a legal undefined constant of the program and if so, of what type it is. + if (program.hasConstant(constantName)) { + // Get the actual constant and check whether it's in fact undefined. + auto const& constant = program.getConstant(constantName); + LOG_THROW(!constant.isDefined(), storm::exceptions::InvalidArgumentException, "Illegally trying to define already defined constant '" << constantName <<"'."); + LOG_THROW(definedConstants.find(constantName) == definedConstants.end(), storm::exceptions::InvalidArgumentException, "Illegally trying to define constant '" << constantName <<"' twice."); + definedConstants.insert(constantName); + + if (constant.getType() == storm::expressions::ExpressionReturnType::Bool) { + if (value == "true") { + constantDefinitions[constantName] = storm::expressions::Expression::createTrue(); + } else if (value == "false") { + constantDefinitions[constantName] = storm::expressions::Expression::createFalse(); + } else { + throw storm::exceptions::InvalidArgumentException() << "Illegal value for boolean constant: " << value << "."; + } + } else if (constant.getType() == storm::expressions::ExpressionReturnType::Int) { + int_fast64_t integerValue = std::stoi(value); + constantDefinitions[constantName] = storm::expressions::Expression::createIntegerLiteral(integerValue); + } else if (constant.getType() == storm::expressions::ExpressionReturnType::Double) { + double doubleValue = std::stod(value); + constantDefinitions[constantName] = storm::expressions::Expression::createDoubleLiteral(doubleValue); + } + } else { + throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: unknown undefined constant " << constantName << "."; + } + } + } + + return constantDefinitions; + } + /*! * Convert the program given at construction time to an abstract model. The type of the model is the one * specified in the program. The given reward model name selects the rewards that the model will contain. @@ -90,24 +156,33 @@ namespace storm { * rewards. * @return The explicit model that was given by the probabilistic program. */ - static std::unique_ptr<storm::models::AbstractModel<ValueType>> translateProgram(storm::ir::Program program, std::string const& constantDefinitionString = "", std::string const& rewardModelName = "") { + static std::unique_ptr<storm::models::AbstractModel<ValueType>> translateProgram(storm::prism::Program program, std::string const& constantDefinitionString = "", std::string const& rewardModelName = "") { // Start by defining the undefined constants in the model. - defineUndefinedConstants(program, constantDefinitionString); + // First, we need to parse the constant definition string. + std::map<std::string, storm::expressions::Expression> constantDefinitions = parseConstantDefinitionString(program, constantDefinitionString); + + storm::prism::Program preparedProgram = program.defineUndefinedConstants(constantDefinitions); + LOG_THROW(!preparedProgram.hasUndefinedConstants(), storm::exceptions::InvalidArgumentException, "Program still contains undefined constants."); + + // Now that we have defined all the constants in the program, we need to substitute their appearances in + // all expressions in the program so we can then evaluate them without having to store the values of the + // constants in the state (i.e., valuation). + preparedProgram = preparedProgram.substituteConstants(); - ModelComponents modelComponents = buildModelComponents(program, rewardModelName); + ModelComponents modelComponents = buildModelComponents(preparedProgram, rewardModelName); std::unique_ptr<storm::models::AbstractModel<ValueType>> result; switch (program.getModelType()) { - case storm::ir::Program::DTMC: + case storm::prism::Program::ModelType::DTMC: result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Dtmc<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling))); break; - case storm::ir::Program::CTMC: + case storm::prism::Program::ModelType::CTMC: result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Ctmc<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling))); break; - case storm::ir::Program::MDP: + case storm::prism::Program::ModelType::MDP: result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Mdp<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling))); break; - case storm::ir::Program::CTMDP: + case storm::prism::Program::ModelType::CTMDP: result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Ctmdp<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling))); break; default: @@ -116,36 +191,19 @@ namespace storm { break; } - // Undefine the constants so that the program can be used again somewhere else. - undefineUndefinedConstants(program); - return result; } private: - /*! - * Transforms a state into a somewhat readable string. - * - * @param state The state to transform into a string. - * @return A string representation of the state. - */ - static std::string toString(StateType const* state) { - std::stringstream ss; - for (unsigned int i = 0; i < state->first.size(); i++) ss << state->first[i] << "\t"; - for (unsigned int i = 0; i < state->second.size(); i++) ss << state->second[i] << "\t"; - return ss.str(); - } - /*! * Applies an update to the given state and returns the resulting new state object. This methods does not * modify the given state but returns a new one. * - * @param variableInformation A structure with information about the variables in the program. * @params state The state to which to apply the update. * @params update The update to apply. * @return The resulting state. */ - static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, storm::ir::Update const& update) { + static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, storm::prism::Update const& update) { return applyUpdate(variableInformation, state, state, update); } @@ -154,26 +212,28 @@ namespace storm { * over the variable values of the given base state. This methods does not modify the given state but * returns a new one. * - * @param variableInformation A structure with information about the variables in the program. * @param state The state to which to apply the update. * @param baseState The state used for evaluating the update. * @param update The update to apply. * @return The resulting state. */ - static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, StateType const* baseState, storm::ir::Update const& update) { + static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, StateType const* baseState, storm::prism::Update const& update) { StateType* newState = new StateType(*state); - for (auto variableAssignmentPair : update.getBooleanAssignments()) { - setValue(newState, variableInformation.booleanVariableToIndexMap.at(variableAssignmentPair.first), variableAssignmentPair.second.getExpression()->getValueAsBool(baseState)); - } - for (auto variableAssignmentPair : update.getIntegerAssignments()) { - int_fast64_t newVariableValue = variableAssignmentPair.second.getExpression()->getValueAsInt(baseState); - bool isLegalValueForVariable = newVariableValue >= variableInformation.lowerBounds.at(variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first)) && newVariableValue <= variableInformation.upperBounds.at(variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first)); - - if (!isLegalValueForVariable) { - throw storm::exceptions::InvalidStateException() << "Invalid value '" << newVariableValue << "' for variable \"" << variableInformation.integerVariables.at(variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first)).getName() << "\". Please strengthen the guards if necessary or enlarge the domains of the variables."; + + // This variable needs to be declared prior to the switch, because of C++ rules. + int_fast64_t newValue = 0; + for (auto const& assignment : update.getAssignments()) { + switch (assignment.getExpression().getReturnType()) { + case storm::expressions::ExpressionReturnType::Bool: newState->setBooleanValue(assignment.getVariableName(), assignment.getExpression().evaluateAsBool(baseState)); break; + case storm::expressions::ExpressionReturnType::Int: + { + newValue = assignment.getExpression().evaluateAsInt(baseState); + auto const& boundsPair = variableInformation.variableToBoundsMap.find(assignment.getVariableName()); + LOG_THROW(boundsPair->second.first <= newValue && newValue <= boundsPair->second.second, storm::exceptions::InvalidArgumentException, "Invalid value " << newValue << " for variable '" << assignment.getVariableName() << "'."); + newState->setIntegerValue(assignment.getVariableName(), newValue); break; + } + default: LOG_ASSERT(false, "Invalid type of assignment."); break; } - - setValue(newState, variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first), newVariableValue); } return newState; } @@ -220,32 +280,32 @@ namespace storm { * @param action The action label to select. * @return A list of lists of active commands or nothing. */ - static boost::optional<std::vector<std::list<storm::ir::Command>>> getActiveCommandsByAction(storm::ir::Program const& program, StateType const* state, std::string const& action) { - boost::optional<std::vector<std::list<storm::ir::Command>>> result((std::vector<std::list<storm::ir::Command>>())); + static boost::optional<std::vector<std::list<storm::prism::Command>>> getActiveCommandsByAction(storm::prism::Program const& program, StateType const* state, std::string const& action) { + boost::optional<std::vector<std::list<storm::prism::Command>>> result((std::vector<std::list<storm::prism::Command>>())); // Iterate over all modules. for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) { - storm::ir::Module const& module = program.getModule(i); + storm::prism::Module const& module = program.getModule(i); // If the module has no command labeled with the given action, we can skip this module. if (!module.hasAction(action)) { continue; } - std::set<uint_fast64_t> const& commandIndices = module.getCommandsByAction(action); + std::set<uint_fast64_t> const& commandIndices = module.getCommandIndicesByAction(action); // If the module contains the action, but there is no command in the module that is labeled with // this action, we don't have any feasible command combinations. if (commandIndices.empty()) { - return boost::optional<std::vector<std::list<storm::ir::Command>>>(); + return boost::optional<std::vector<std::list<storm::prism::Command>>>(); } - std::list<storm::ir::Command> commands; + std::list<storm::prism::Command> commands; // Look up commands by their indices and add them if the guard evaluates to true in the given state. for (uint_fast64_t commandIndex : commandIndices) { - storm::ir::Command const& command = module.getCommand(commandIndex); - if (command.getGuard()->getValueAsBool(state)) { + storm::prism::Command const& command = module.getCommand(commandIndex); + if (command.getGuardExpression().evaluateAsBool(state)) { commands.push_back(command); } } @@ -253,7 +313,7 @@ namespace storm { // If there was no enabled command although the module has some command with the required action label, // we must not return anything. if (commands.size() == 0) { - return boost::optional<std::vector<std::list<storm::ir::Command>>>(); + return boost::optional<std::vector<std::list<storm::prism::Command>>>(); } result.get().push_back(std::move(commands)); @@ -261,23 +321,26 @@ namespace storm { return result; } - static std::list<Choice<ValueType>> getUnlabeledTransitions(storm::ir::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) { + static std::list<Choice<ValueType>> getUnlabeledTransitions(storm::prism::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) { std::list<Choice<ValueType>> result; StateType const* currentState = stateInformation.reachableStates[stateIndex]; // Iterate over all modules. for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) { - storm::ir::Module const& module = program.getModule(i); + storm::prism::Module const& module = program.getModule(i); // Iterate over all commands. for (uint_fast64_t j = 0; j < module.getNumberOfCommands(); ++j) { - storm::ir::Command const& command = module.getCommand(j); + storm::prism::Command const& command = module.getCommand(j); // Only consider unlabeled commands. if (command.getActionName() != "") continue; + // Skip the command, if it is not enabled. - if (!command.getGuard()->getValueAsBool(currentState)) continue; + if (!command.getGuardExpression().evaluateAsBool(currentState)) { + continue; + } result.push_back(Choice<ValueType>("")); Choice<ValueType>& choice = result.back(); @@ -286,7 +349,7 @@ namespace storm { double probabilitySum = 0; // Iterate over all updates of the current command. for (uint_fast64_t k = 0; k < command.getNumberOfUpdates(); ++k) { - storm::ir::Update const& update = command.getUpdate(k); + storm::prism::Update const& update = command.getUpdate(k); // Obtain target state index. std::pair<bool, uint_fast64_t> flagTargetStateIndexPair = getOrAddStateIndex(applyUpdate(variableInformation, currentState, update), stateInformation); @@ -297,7 +360,7 @@ namespace storm { } // Update the choice by adding the probability/target state to it. - double probabilityToAdd = update.getLikelihoodExpression()->getValueAsDouble(currentState); + double probabilityToAdd = update.getLikelihoodExpression().evaluateAsDouble(currentState); probabilitySum += probabilityToAdd; boost::container::flat_set<uint_fast64_t> labels; labels.insert(update.getGlobalIndex()); @@ -305,27 +368,24 @@ namespace storm { } // Check that the resulting distribution is in fact a distribution. - if (std::abs(1 - probabilitySum) > storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()) { - LOG4CPLUS_ERROR(logger, "Sum of update probabilities should be one for command:\n\t" << command.toString()); - throw storm::exceptions::WrongFormatException() << "Sum of update probabilities should be one for command:\n\t" << command.toString(); - } + LOG_THROW(std::abs(1 - probabilitySum) < storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble(), storm::exceptions::WrongFormatException, "Probabilities do not sum to one for command '" << command << "'."); } } return result; } - static std::list<Choice<ValueType>> getLabeledTransitions(storm::ir::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) { + static std::list<Choice<ValueType>> getLabeledTransitions(storm::prism::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) { std::list<Choice<ValueType>> result; for (std::string const& action : program.getActions()) { StateType const* currentState = stateInformation.reachableStates[stateIndex]; - boost::optional<std::vector<std::list<storm::ir::Command>>> optionalActiveCommandLists = getActiveCommandsByAction(program, currentState, action); + boost::optional<std::vector<std::list<storm::prism::Command>>> optionalActiveCommandLists = getActiveCommandsByAction(program, currentState, action); // Only process this action label, if there is at least one feasible solution. if (optionalActiveCommandLists) { - std::vector<std::list<storm::ir::Command>> const& activeCommandList = optionalActiveCommandLists.get(); - std::vector<std::list<storm::ir::Command>::const_iterator> iteratorList(activeCommandList.size()); + std::vector<std::list<storm::prism::Command>> const& activeCommandList = optionalActiveCommandLists.get(); + std::vector<std::list<storm::prism::Command>::const_iterator> iteratorList(activeCommandList.size()); // Initialize the list of iterators. for (size_t i = 0; i < activeCommandList.size(); ++i) { @@ -342,17 +402,17 @@ namespace storm { // FIXME: This does not check whether a global variable is written multiple times. While the // behaviour for this is undefined anyway, a warning should be issued in that case. for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) { - storm::ir::Command const& command = *iteratorList[i]; + storm::prism::Command const& command = *iteratorList[i]; for (uint_fast64_t j = 0; j < command.getNumberOfUpdates(); ++j) { - storm::ir::Update const& update = command.getUpdate(j); + storm::prism::Update const& update = command.getUpdate(j); for (auto const& stateProbabilityPair : *currentTargetStates) { StateType* newTargetState = applyUpdate(variableInformation, stateProbabilityPair.first, currentState, update); storm::storage::LabeledValues<double> newProbability; - double updateProbability = update.getLikelihoodExpression()->getValueAsDouble(currentState); + double updateProbability = update.getLikelihoodExpression().evaluateAsDouble(currentState); for (auto const& valueLabelSetPair : stateProbabilityPair.second) { // Copy the label set, so we can modify it. boost::container::flat_set<uint_fast64_t> newLabelSet = valueLabelSetPair.second; @@ -459,13 +519,29 @@ namespace storm { * @return A tuple containing a vector with all rows at which the nondeterministic choices of each state begin * and a vector containing the labels associated with each choice. */ - static std::vector<boost::container::flat_set<uint_fast64_t>> buildMatrices(storm::ir::Program const& program, VariableInformation const& variableInformation, std::vector<storm::ir::TransitionReward> const& transitionRewards, StateInformation& stateInformation, bool deterministicModel, storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, storm::storage::SparseMatrixBuilder<ValueType>& transitionRewardMatrixBuilder) { + static std::vector<boost::container::flat_set<uint_fast64_t>> buildMatrices(storm::prism::Program const& program, VariableInformation const& variableInformation, std::vector<storm::prism::TransitionReward> const& transitionRewards, StateInformation& stateInformation, bool deterministicModel, storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, storm::storage::SparseMatrixBuilder<ValueType>& transitionRewardMatrixBuilder) { std::vector<boost::container::flat_set<uint_fast64_t>> choiceLabels; // Initialize a queue and insert the initial state. std::queue<uint_fast64_t> stateQueue; - StateType* initialState = getInitialState(program, variableInformation); - getOrAddStateIndex(initialState, stateInformation); + StateType* initialState = new StateType; + for (auto const& booleanVariable : program.getGlobalBooleanVariables()) { + initialState->addBooleanIdentifier(booleanVariable.getName(), booleanVariable.getInitialValueExpression().evaluateAsBool()); + } + for (auto const& integerVariable : program.getGlobalIntegerVariables()) { + initialState->addIntegerIdentifier(integerVariable.getName(), integerVariable.getInitialValueExpression().evaluateAsInt()); + } + for (auto const& module : program.getModules()) { + for (auto const& booleanVariable : module.getBooleanVariables()) { + initialState->addBooleanIdentifier(booleanVariable.getName(), booleanVariable.getInitialValueExpression().evaluateAsBool()); + } + for (auto const& integerVariable : module.getIntegerVariables()) { + initialState->addIntegerIdentifier(integerVariable.getName(), integerVariable.getInitialValueExpression().evaluateAsInt()); + } + } + + std::pair<bool, uint_fast64_t> addIndexPair = getOrAddStateIndex(initialState, stateInformation); + stateInformation.initialStateIndices.push_back(addIndexPair.second); stateQueue.push(stateInformation.stateToIndexMap[initialState]); // Now explore the current state until there is no more reachable state. @@ -505,8 +581,8 @@ namespace storm { // Now add all rewards that match this choice. for (auto const& transitionReward : transitionRewards) { - if (transitionReward.getActionName() == "" && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) { - stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState))); + if (transitionReward.getActionName() == "" && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) { + stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState))); } } } @@ -518,8 +594,8 @@ namespace storm { // Now add all rewards that match this choice. for (auto const& transitionReward : transitionRewards) { - if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) { - stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState))); + if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) { + stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState))); } } } @@ -556,8 +632,8 @@ namespace storm { // Now add all rewards that match this choice. for (auto const& transitionReward : transitionRewards) { - if (transitionReward.getActionName() == "" && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) { - stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState))); + if (transitionReward.getActionName() == "" && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) { + stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState))); } } @@ -583,8 +659,8 @@ namespace storm { // Now add all rewards that match this choice. for (auto const& transitionReward : transitionRewards) { - if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) { - stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState))); + if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) { + stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState))); } } @@ -616,20 +692,28 @@ namespace storm { * is considered. * @return A structure containing the components of the resulting model. */ - static ModelComponents buildModelComponents(storm::ir::Program const& program, std::string const& rewardModelName) { + static ModelComponents buildModelComponents(storm::prism::Program const& program, std::string const& rewardModelName) { ModelComponents modelComponents; - VariableInformation variableInformation = createVariableInformation(program); + VariableInformation variableInformation; + for (auto const& integerVariable : program.getGlobalIntegerVariables()) { + variableInformation.variableToBoundsMap[integerVariable.getName()] = std::make_pair(integerVariable.getLowerBoundExpression().evaluateAsInt(), integerVariable.getUpperBoundExpression().evaluateAsInt()); + } + for (auto const& module : program.getModules()) { + for (auto const& integerVariable : module.getIntegerVariables()) { + variableInformation.variableToBoundsMap[integerVariable.getName()] = std::make_pair(integerVariable.getLowerBoundExpression().evaluateAsInt(), integerVariable.getUpperBoundExpression().evaluateAsInt()); + } + } // Create the structure for storing the reachable state space. StateInformation stateInformation; // Get the selected reward model or create an empty one if none is selected. - storm::ir::RewardModel const& rewardModel = rewardModelName != "" ? program.getRewardModel(rewardModelName) : storm::ir::RewardModel(); + storm::prism::RewardModel const& rewardModel = rewardModelName != "" ? program.getRewardModel(rewardModelName) : storm::prism::RewardModel(); // Determine whether we have to combine different choices to one or whether this model can have more than // one choice per state. - bool deterministicModel = program.getModelType() == storm::ir::Program::DTMC || program.getModelType() == storm::ir::Program::CTMC; + bool deterministicModel = program.getModelType() == storm::prism::Program::ModelType::DTMC || program.getModelType() == storm::prism::Program::ModelType::CTMC; // Build the transition and reward matrices. storm::storage::SparseMatrixBuilder<ValueType> transitionMatrixBuilder(0, 0, 0, !deterministicModel, 0); @@ -662,30 +746,29 @@ namespace storm { * @param stateInformation Information about the state space of the program. * @return The state labeling of the given program. */ - static storm::models::AtomicPropositionsLabeling buildStateLabeling(storm::ir::Program const& program, VariableInformation const& variableInformation, StateInformation const& stateInformation) { - std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& labels = program.getLabels(); + static storm::models::AtomicPropositionsLabeling buildStateLabeling(storm::prism::Program const& program, VariableInformation const& variableInformation, StateInformation const& stateInformation) { + std::vector<storm::prism::Label> const& labels = program.getLabels(); storm::models::AtomicPropositionsLabeling result(stateInformation.reachableStates.size(), labels.size() + 1); // Initialize labeling. - for (auto const& labelExpressionPair : labels) { - result.addAtomicProposition(labelExpressionPair.first); + for (auto const& label : labels) { + result.addAtomicProposition(label.getName()); } for (uint_fast64_t index = 0; index < stateInformation.reachableStates.size(); index++) { - for (auto const& labelExpressionPair: labels) { + for (auto const& label : labels) { // Add label to state, if the corresponding expression is true. - if (labelExpressionPair.second->getValueAsBool(stateInformation.reachableStates[index])) { - result.addAtomicPropositionToState(labelExpressionPair.first, index); + if (label.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates[index])) { + result.addAtomicPropositionToState(label.getName(), index); } } } // Also label the initial state with the special label "init". result.addAtomicProposition("init"); - StateType* initialState = getInitialState(program, variableInformation); - uint_fast64_t initialIndex = stateInformation.stateToIndexMap.at(initialState); - result.addAtomicPropositionToState("init", initialIndex); - delete initialState; + for (auto const& index : stateInformation.initialStateIndices) { + result.addAtomicPropositionToState("init", index); + } return result; } @@ -697,14 +780,14 @@ namespace storm { * @param stateInformation Information about the state space. * @return A vector containing the state rewards for the state space. */ - static std::vector<ValueType> buildStateRewards(std::vector<storm::ir::StateReward> const& rewards, StateInformation const& stateInformation) { + static std::vector<ValueType> buildStateRewards(std::vector<storm::prism::StateReward> const& rewards, StateInformation const& stateInformation) { std::vector<ValueType> result(stateInformation.reachableStates.size()); for (uint_fast64_t index = 0; index < stateInformation.reachableStates.size(); index++) { result[index] = ValueType(0); for (auto const& reward : rewards) { // Add this reward to the state if the state is included in the state reward. - if (reward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates[index])) { - result[index] += ValueType(reward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates[index])); + if (reward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates[index])) { + result[index] += ValueType(reward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates[index])); } } } diff --git a/src/counterexamples/MILPMinimalLabelSetGenerator.h b/src/counterexamples/MILPMinimalLabelSetGenerator.h index de9c6b057..197db76ab 100644 --- a/src/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/counterexamples/MILPMinimalLabelSetGenerator.h @@ -11,7 +11,7 @@ #include <chrono> #include "src/models/Mdp.h" -#include "src/ir/Program.h" +#include "src/storage/prism/Program.h" #include "src/exceptions/NotImplementedException.h" #include "src/exceptions/InvalidArgumentException.h" #include "src/exceptions/InvalidStateException.h" @@ -92,8 +92,7 @@ namespace storm { StateInformation result; result.relevantStates = storm::utility::graph::performProbGreater0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates); result.relevantStates &= ~psiStates; - result.problematicStates = storm::utility::graph::performProbGreater0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates); - result.problematicStates.complement(); + result.problematicStates = storm::utility::graph::performProb0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates); result.problematicStates &= result.relevantStates; LOG4CPLUS_DEBUG(logger, "Found " << phiStates.getNumberOfSetBits() << " filter states."); LOG4CPLUS_DEBUG(logger, "Found " << psiStates.getNumberOfSetBits() << " target states."); @@ -1001,7 +1000,7 @@ namespace storm { * @param formulaPtr A pointer to a safety formula. The outermost operator must be a probabilistic bound operator with a strict upper bound. The nested * formula can be either an unbounded until formula or an eventually formula. */ - static void computeCounterexample(storm::ir::Program const& program, storm::models::Mdp<T> const& labeledMdp, storm::property::prctl::AbstractPrctlFormula<double> const* formulaPtr) { + static void computeCounterexample(storm::prism::Program const& program, storm::models::Mdp<T> const& labeledMdp, storm::property::prctl::AbstractPrctlFormula<double> const* formulaPtr) { std::cout << std::endl << "Generating minimal label counterexample for formula " << formulaPtr->toString() << std::endl; // First, we need to check whether the current formula is an Until-Formula. storm::property::prctl::ProbabilisticBoundOperator<double> const* probBoundFormula = dynamic_cast<storm::property::prctl::ProbabilisticBoundOperator<double> const*>(formulaPtr); @@ -1046,9 +1045,8 @@ namespace storm { std::cout << std::endl << "Computed minimal label set of size " << usedLabelSet.size() << " in " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() << "ms." << std::endl; std::cout << "Resulting program:" << std::endl; - storm::ir::Program restrictedProgram(program); - restrictedProgram.restrictCommands(usedLabelSet); - std::cout << restrictedProgram.toString() << std::endl; + storm::prism::Program restrictedProgram = program.restrictCommands(usedLabelSet); + std::cout << restrictedProgram << std::endl; std::cout << std::endl << "-------------------------------------------" << std::endl; // FIXME: Return the DTMC that results from applying the max scheduler in the MDP restricted to the computed label set. diff --git a/src/counterexamples/SMTMinimalCommandSetGenerator.h b/src/counterexamples/SMTMinimalCommandSetGenerator.h index f95bc2806..da5d4a7ad 100644 --- a/src/counterexamples/SMTMinimalCommandSetGenerator.h +++ b/src/counterexamples/SMTMinimalCommandSetGenerator.h @@ -25,7 +25,7 @@ #include "src/solver/GmmxxNondeterministicLinearEquationSolver.h" #include "src/utility/counterexamples.h" -#include "src/utility/IRUtility.h" +#include "src/utility/PrismUtility.h" namespace storm { namespace counterexamples { diff --git a/src/exceptions/ExceptionMacros.h b/src/exceptions/ExceptionMacros.h new file mode 100644 index 000000000..09e7058ec --- /dev/null +++ b/src/exceptions/ExceptionMacros.h @@ -0,0 +1,31 @@ +#ifndef STORM_EXCEPTIONS_EXCEPTIONMACROS_H_ +#define STORM_EXCEPTIONS_EXCEPTIONMACROS_H_ + +#include <cassert> + +#include "log4cplus/logger.h" +#include "log4cplus/loggingmacros.h" + +extern log4cplus::Logger logger; + +#ifndef NDEBUG +#define LOG_ASSERT(cond, message) \ +{ \ + if (!(cond)) { \ + LOG4CPLUS_ERROR(logger, message); \ + assert(cond); \ + } \ +} while (false) +#else +#define LOG_ASSERT(cond, message) /* empty */ +#endif + +#define LOG_THROW(cond, exception, message) \ +{ \ +if (!(cond)) { \ +LOG4CPLUS_ERROR(logger, message); \ +throw exception() << message; \ +} \ +} while (false) + +#endif /* STORM_EXCEPTIONS_EXCEPTIONMACROS_H_ */ \ No newline at end of file diff --git a/src/exceptions/InvalidOperationException.h b/src/exceptions/InvalidOperationException.h new file mode 100644 index 000000000..728f7ff1c --- /dev/null +++ b/src/exceptions/InvalidOperationException.h @@ -0,0 +1,17 @@ +#ifndef STORM_EXCEPTIONS_INVALIDOPERATIONEXCEPTION_H_ +#define STORM_EXCEPTIONS_INVALIDOPERATIONEXCEPTION_H_ + +#include "src/exceptions/BaseException.h" + +namespace storm { + + namespace exceptions { + + /*! + * @brief This exception is thrown when an operation is invalid in this context + */ + STORM_EXCEPTION_DEFINE_NEW(InvalidOperationException) + + } // namespace exceptions +} // namespace storm +#endif // STORM_EXCEPTIONS_INVALIDOPERATIONEXCEPTION_H_ diff --git a/src/exceptions/InvalidTypeException.h b/src/exceptions/InvalidTypeException.h new file mode 100644 index 000000000..de2874218 --- /dev/null +++ b/src/exceptions/InvalidTypeException.h @@ -0,0 +1,18 @@ +#ifndef STORM_EXCEPTIONS_INVALIDTYPEEXCEPTION_H_ +#define STORM_EXCEPTIONS_INVALIDTYPEEXCEPTION_H_ + +#include "src/exceptions/BaseException.h" + +namespace storm { + + namespace exceptions { + + /*! + * @brief This exception is thrown when a type is invalid in this context + */ + STORM_EXCEPTION_DEFINE_NEW(InvalidTypeException) + + } // namespace exceptions + +} // namespace storm +#endif // STORM_EXCEPTIONS_INVALIDTYPEEXCEPTION_H_ diff --git a/src/ir/Assignment.cpp b/src/ir/Assignment.cpp deleted file mode 100644 index a50847afb..000000000 --- a/src/ir/Assignment.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Assignment.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "Assignment.h" -#include "src/parser/prismparser/VariableState.h" - -namespace storm { - namespace ir { - - Assignment::Assignment() : variableName(), expression() { - // Nothing to do here. - } - - Assignment::Assignment(std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& expression) - : variableName(variableName), expression(std::move(expression)) { - // Nothing to do here. - } - - Assignment::Assignment(Assignment const& oldAssignment, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) - : variableName(oldAssignment.variableName), expression(oldAssignment.expression->clone(renaming, variableState)) { - auto renamingPair = renaming.find(oldAssignment.variableName); - if (renamingPair != renaming.end()) { - this->variableName = renamingPair->second; - } - } - - Assignment::Assignment(Assignment const& otherAssignment) : variableName(otherAssignment.variableName), expression() { - if (otherAssignment.expression != nullptr) { - expression = otherAssignment.expression->clone(); - } - } - - Assignment& Assignment::operator=(Assignment const& otherAssignment) { - if (this != &otherAssignment) { - this->variableName = otherAssignment.variableName; - this->expression = otherAssignment.expression->clone(); - } - - return *this; - } - - std::string const& Assignment::getVariableName() const { - return variableName; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& Assignment::getExpression() const { - return expression; - } - - std::string Assignment::toString() const { - std::stringstream result; - result << "(" << variableName << "' = " << expression->toString() << ")"; - return result.str(); - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/Assignment.h b/src/ir/Assignment.h deleted file mode 100644 index 12d96a413..000000000 --- a/src/ir/Assignment.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Assignment.h - * - * Created on: 06.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_ASSIGNMENT_H_ -#define STORM_IR_ASSIGNMENT_H_ - -#include <memory> - -#include "expressions/BaseExpression.h" - -namespace storm { - - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - - /*! - * A class representing the assignment of an expression to a variable. - */ - class Assignment { - public: - /*! - * Default constructor. Creates an empty assignment. - */ - Assignment(); - - /*! - * Constructs an assignment using the given variable name and expression. - * - * @param variableName The variable that this assignment targets. - * @param expression The expression to assign to the variable. - */ - Assignment(std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& expression); - - /*! - * Creates a copy of the given assignment and performs the provided renaming. - * - * @param oldAssignment The assignment to copy. - * @param renaming A mapping from names that are to be renamed to the names they are to be - * replaced with. - * @param variableState An object knowing about the variables in the system. - */ - Assignment(Assignment const& oldAssignment, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState); - - /*! - * Performs a deep-copy of the given assignment. - * - * @param otherAssignment The assignment to copy. - */ - Assignment(Assignment const& otherAssignment); - - /*! - * Performs a deep-copy of the given assignment and assigns it to the current one. - * - * @param otherAssignment The assignment to assign. - */ - Assignment& operator=(Assignment const& otherAssignment); - - /*! - * Retrieves the name of the variable that this assignment targets. - * - * @return The name of the variable that this assignment targets. - */ - std::string const& getVariableName() const; - - /*! - * Retrieves the expression that is assigned to the variable. - * - * @return The expression that is assigned to the variable. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getExpression() const; - - /*! - * Retrieves a string representation of this assignment. - * @returns a string representation of this assignment. - */ - std::string toString() const; - - private: - // The name of the variable that this assignment targets. - std::string variableName; - - // The expression that is assigned to the variable. - std::unique_ptr<storm::ir::expressions::BaseExpression> expression; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_ASSIGNMENT_H_ */ diff --git a/src/ir/BooleanVariable.cpp b/src/ir/BooleanVariable.cpp deleted file mode 100644 index 843655be9..000000000 --- a/src/ir/BooleanVariable.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * BooleanVariable.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "BooleanVariable.h" -#include "src/parser/prismparser/VariableState.h" - -namespace storm { - namespace ir { - - BooleanVariable::BooleanVariable() : Variable() { - // Nothing to do here. - } - - BooleanVariable::BooleanVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue) - : Variable(localIndex, globalIndex, variableName, std::move(initialValue)) { - // Nothing to do here. - } - - BooleanVariable::BooleanVariable(BooleanVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) - : Variable(oldVariable, newName, newGlobalIndex, renaming, variableState) { - // Nothing to do here. - } - - BooleanVariable& BooleanVariable::operator=(BooleanVariable const& otherVariable) { - if (this != &otherVariable) { - Variable::operator=(otherVariable); - } - - return *this; - } - - std::string BooleanVariable::toString() const { - std::stringstream result; - result << this->getName() << ": bool"; - if (this->getInitialValue() != nullptr) { - result << " init " << this->getInitialValue()->toString(); - } - result << ";"; - return result.str(); - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/BooleanVariable.h b/src/ir/BooleanVariable.h deleted file mode 100644 index b968d7890..000000000 --- a/src/ir/BooleanVariable.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * BooleanVariable.h - * - * Created on: 08.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_BOOLEANVARIABLE_H_ -#define STORM_IR_BOOLEANVARIABLE_H_ - -#include <memory> -#include <map> - -#include "src/ir/Variable.h" - -namespace storm { - - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - - /*! - * A class representing a boolean variable. - */ - class BooleanVariable : public Variable { - public: - /*! - * Default constructor. Creates a boolean variable without a name. - */ - BooleanVariable(); - - /*! - * Creates a boolean variable with the given name and the given initial value. - * - * @param localIndex A module-local unique index for the variable. - * @param globalIndex A globally unique index for the variable. - * @param variableName The name of the variable. - * @param initialValue The expression that defines the initial value of the variable. - */ - BooleanVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue = nullptr); - - /*! - * Creates a copy of the given boolean variable and performs the provided renaming. - * - * @param oldVariable The variable to copy. - * @param newName New name of this variable. - * @param newGlobalIndex The new global index of the variable. - * @param renaming A mapping from names that are to be renamed to the names they are to be - * replaced with. - * @param variableState An object knowing about the variables in the system. - */ - BooleanVariable(BooleanVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState); - - BooleanVariable& operator=(BooleanVariable const& otherVariable); - - /*! - * Retrieves a string representation of this variable. - * @returns a string representation of this variable. - */ - std::string toString() const; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_BOOLEANVARIABLE_H_ */ diff --git a/src/ir/Command.cpp b/src/ir/Command.cpp deleted file mode 100644 index dbb1eef64..000000000 --- a/src/ir/Command.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Command.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> -#include <iostream> - -#include "Command.h" -#include "src/parser/prismparser/VariableState.h" - -namespace storm { - namespace ir { - - Command::Command() : actionName(), guardExpression(), updates(), globalIndex() { - // Nothing to do here. - } - - Command::Command(uint_fast64_t globalIndex, std::string const& actionName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& guardExpression, std::vector<storm::ir::Update> const& updates) - : actionName(actionName), guardExpression(std::move(guardExpression)), updates(updates), globalIndex(globalIndex) { - // Nothing to do here. - } - - Command::Command(Command const& oldCommand, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState) - : actionName(oldCommand.getActionName()), guardExpression(oldCommand.guardExpression->clone(renaming, variableState)), globalIndex(newGlobalIndex) { - auto renamingPair = renaming.find(this->actionName); - if (renamingPair != renaming.end()) { - this->actionName = renamingPair->second; - } - this->updates.reserve(oldCommand.getNumberOfUpdates()); - for (Update const& update : oldCommand.updates) { - this->updates.emplace_back(update, variableState.getNextGlobalUpdateIndex(), renaming, variableState); - variableState.nextGlobalUpdateIndex++; - } - } - - Command::Command(Command const& otherCommand) : actionName(otherCommand.actionName), guardExpression(), updates(otherCommand.updates), globalIndex(otherCommand.globalIndex) { - if (otherCommand.guardExpression != nullptr) { - guardExpression = otherCommand.guardExpression->clone(); - } - } - - Command& Command::operator=(Command const& otherCommand) { - if (this != &otherCommand) { - this->actionName = otherCommand.actionName; - this->guardExpression = otherCommand.guardExpression->clone(); - this->updates = otherCommand.updates; - this->globalIndex = otherCommand.globalIndex; - } - - return *this; - } - - std::string const& Command::getActionName() const { - return this->actionName; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& Command::getGuard() const { - return guardExpression; - } - - uint_fast64_t Command::getNumberOfUpdates() const { - return this->updates.size(); - } - - storm::ir::Update const& Command::getUpdate(uint_fast64_t index) const { - return this->updates[index]; - } - - std::vector<storm::ir::Update> const& Command::getUpdates() const { - return this->updates; - } - - uint_fast64_t Command::getGlobalIndex() const { - return this->globalIndex; - } - - std::string Command::toString() const { - std::stringstream result; - result << "[" << actionName << "] " << guardExpression->toString() << " -> "; - for (uint_fast64_t i = 0; i < updates.size(); ++i) { - result << updates[i].toString(); - if (i < updates.size() - 1) { - result << " + "; - } - } - result << ";"; - return result.str(); - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/Command.h b/src/ir/Command.h deleted file mode 100644 index 04efe8b86..000000000 --- a/src/ir/Command.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Command.h - * - * Created on: 06.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_COMMAND_H_ -#define STORM_IR_COMMAND_H_ - -#include <vector> -#include <string> -#include <map> - -#include "expressions/BaseExpression.h" -#include "Update.h" - -namespace storm { - - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - - /*! - * A class representing a command. - */ - class Command { - public: - /*! - * Default constructor. Creates a a command without name, guard and updates. - */ - Command(); - - /*! - * Creates a command with the given name, guard and updates. - * - * @param globalIndex The global index of the command. - * @param actionName The action name of the command. - * @param guardExpression the expression that defines the guard of the command. - * @param updates A list of updates that is associated with this command. - */ - Command(uint_fast64_t globalIndex, std::string const& actionName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& guardExpression, std::vector<storm::ir::Update> const& updates); - - /*! - * Creates a copy of the given command and performs the provided renaming. - * - * @param oldCommand The command to copy. - * @param newGlobalIndex The global index of the copy of the command. - * @param renaming A mapping from names that are to be renamed to the names they are to be - * replaced with. - * @param variableState An object knowing about the variables in the system. - */ - Command(Command const& oldCommand, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState); - - /*! - * Performs a deep-copy of the given command. - * - * @param otherCommand The command to copy. - */ - Command(Command const& otherCommand); - - Command& operator=(Command const& otherCommand); - - /*! - * Retrieves the action name of this command. - * - * @return The action name of this command. - */ - std::string const& getActionName() const; - - /*! - * Retrieves a reference to the guard of the command. - * - * @return A reference to the guard of the command. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getGuard() const; - - /*! - * Retrieves the number of updates associated with this command. - * - * @return The number of updates associated with this command. - */ - uint_fast64_t getNumberOfUpdates() const; - - /*! - * Retrieves a reference to the update with the given index. - * - * @return A reference to the update with the given index. - */ - storm::ir::Update const& getUpdate(uint_fast64_t index) const; - - /*! - * Retrieves a vector of all updates associated with this command. - * - * @return A vector of updates associated with this command. - */ - std::vector<storm::ir::Update> const& getUpdates() const; - - /*! - * Retrieves the global index of the command, that is, a unique index over all modules. - * - * @return The global index of the command. - */ - uint_fast64_t getGlobalIndex() const; - - /*! - * Retrieves a string representation of this command. - * - * @return A string representation of this command. - */ - std::string toString() const; - - private: - // The name of the command. - std::string actionName; - - // The expression that defines the guard of the command. - std::unique_ptr<storm::ir::expressions::BaseExpression> guardExpression; - - // The list of updates of the command. - std::vector<storm::ir::Update> updates; - - // The global index of the command. - uint_fast64_t globalIndex; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_COMMAND_H_ */ diff --git a/src/ir/IR.h b/src/ir/IR.h deleted file mode 100644 index 80a794002..000000000 --- a/src/ir/IR.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * IR.h - * - * Created on: 06.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_IR_H_ -#define STORM_IR_IR_H_ - -// Bundle all headers to make it easy to include them. -#include "expressions/Expressions.h" -#include "Assignment.h" -#include "Update.h" -#include "Command.h" -#include "Variable.h" -#include "BooleanVariable.h" -#include "IntegerVariable.h" -#include "Module.h" -#include "StateReward.h" -#include "TransitionReward.h" -#include "RewardModel.h" -#include "Program.h" - -#endif /* STORM_IR_IR_H_ */ diff --git a/src/ir/IntegerVariable.cpp b/src/ir/IntegerVariable.cpp deleted file mode 100644 index b98b30d07..000000000 --- a/src/ir/IntegerVariable.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * IntegerVariable.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> -#include <iostream> - -#include "IntegerVariable.h" -#include "src/parser/prismparser/VariableState.h" - -namespace storm { - namespace ir { - - IntegerVariable::IntegerVariable() : lowerBound(), upperBound() { - // Nothing to do here. - } - - IntegerVariable::IntegerVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& lowerBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& upperBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue) - : Variable(localIndex, globalIndex, variableName, std::move(initialValue)), lowerBound(std::move(lowerBound)), upperBound(std::move(upperBound)) { - // Nothing to do here. - } - - IntegerVariable::IntegerVariable(IntegerVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) - : Variable(oldVariable, newName, newGlobalIndex, renaming, variableState), lowerBound(oldVariable.lowerBound->clone(renaming, variableState)), upperBound(oldVariable.upperBound->clone(renaming, variableState)) { - // Nothing to do here. - } - - IntegerVariable::IntegerVariable(IntegerVariable const& otherVariable) : Variable(otherVariable.getLocalIndex(), otherVariable.getGlobalIndex(), otherVariable.getName(), nullptr), lowerBound(), upperBound() { - if (otherVariable.getInitialValue() != nullptr) { - setInitialValue(otherVariable.getInitialValue()->clone()); - } - if (otherVariable.lowerBound != nullptr) { - lowerBound = otherVariable.lowerBound->clone(); - } - if (otherVariable.upperBound != nullptr) { - upperBound = otherVariable.upperBound->clone(); - } - } - - IntegerVariable& IntegerVariable::operator=(IntegerVariable const& otherVariable) { - if (this != &otherVariable) { - Variable::operator=(otherVariable); - this->lowerBound = otherVariable.lowerBound->clone(); - this->upperBound = otherVariable.upperBound->clone(); - } - - return *this; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& IntegerVariable::getLowerBound() const { - return this->lowerBound; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& IntegerVariable::getUpperBound() const { - return this->upperBound; - } - - std::string IntegerVariable::toString() const { - std::stringstream result; - result << this->getName() << ": [" << lowerBound->toString() << ".." << upperBound->toString() << "]"; - if (this->getInitialValue() != nullptr) { - result << " init " + this->getInitialValue()->toString(); - } - result << ";"; - return result.str(); - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/IntegerVariable.h b/src/ir/IntegerVariable.h deleted file mode 100644 index 930e1d0b8..000000000 --- a/src/ir/IntegerVariable.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * IntegerVariable.h - * - * Created on: 08.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_INTEGERVARIABLE_H_ -#define STORM_IR_INTEGERVARIABLE_H_ - -#include <memory> - -#include "src/ir/Variable.h" -#include "expressions/BaseExpression.h" - -namespace storm { - - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - - /*! - * A class representing an integer variable. - */ - class IntegerVariable : public Variable { - public: - /*! - * Default constructor. Creates an integer variable without a name and lower and upper bounds. - */ - IntegerVariable(); - - /*! - * Creates a boolean variable with the given name and the given initial value. - * - * @param localIndex A module-local unique index for the variable. - * @param globalIndex A globally unique index for the variable. - * @param variableName The name of the variable. - * @param lowerBound the lower bound of the domain of the variable. - * @param upperBound the upper bound of the domain of the variable. - * @param initialValue the expression that defines the initial value of the variable. - */ - IntegerVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& lowerBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& upperBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue = nullptr); - - /*! - * Creates a copy of the given integer variable and performs the provided renaming. - * - * @param oldVariable The variable to copy. - * @param newName New name of this variable. - * @param newGlobalIndex The new global index of the variable. - * @param renaming A mapping from names that are to be renamed to the names they are to be - * replaced with. - * @param variableState An object knowing about the variables in the system. - */ - IntegerVariable(IntegerVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState); - - /*! - * Performs a deep-copy of the given variable. - * - * @param otherVariable The variable to copy. - */ - IntegerVariable(IntegerVariable const& otherVariable); - - IntegerVariable& operator=(IntegerVariable const& otherVariable); - - /*! - * Retrieves the lower bound for this integer variable. - * @returns the lower bound for this integer variable. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getLowerBound() const; - - /*! - * Retrieves the upper bound for this integer variable. - * @returns the upper bound for this integer variable. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getUpperBound() const; - - /*! - * Retrieves a string representation of this variable. - * @returns a string representation of this variable. - */ - std::string toString() const; - - private: - // The lower bound of the domain of the variable. - std::unique_ptr<storm::ir::expressions::BaseExpression> lowerBound; - - // The upper bound of the domain of the variable. - std::unique_ptr<storm::ir::expressions::BaseExpression> upperBound; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_INTEGERVARIABLE_H_ */ diff --git a/src/ir/Module.cpp b/src/ir/Module.cpp deleted file mode 100644 index 5724db8df..000000000 --- a/src/ir/Module.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Module.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> -#include <iostream> -#include "utility/OsDetection.h" - -#include "Module.h" -#include "src/parser/prismparser/VariableState.h" -#include "src/exceptions/OutOfRangeException.h" -#include "src/exceptions/InvalidArgumentException.h" - -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" -extern log4cplus::Logger logger; - -namespace storm { - namespace ir { - - Module::Module() : moduleName(), booleanVariables(), integerVariables(), booleanVariableToLocalIndexMap(), - integerVariableToLocalIndexMap(), commands(), actions(), actionsToCommandIndexMap() { - // Nothing to do here. - } - - Module::Module(std::string const& moduleName, - std::vector<storm::ir::BooleanVariable> const& booleanVariables, - std::vector<storm::ir::IntegerVariable> const& integerVariables, - std::map<std::string, uint_fast64_t> const& booleanVariableToLocalIndexMap, - std::map<std::string, uint_fast64_t> const& integerVariableToLocalIndexMap, - std::vector<storm::ir::Command> const& commands) - : moduleName(moduleName), booleanVariables(booleanVariables), integerVariables(integerVariables), - booleanVariableToLocalIndexMap(booleanVariableToLocalIndexMap), - integerVariableToLocalIndexMap(integerVariableToLocalIndexMap), commands(commands), actions(), actionsToCommandIndexMap() { - // Initialize the internal mappings for fast information retrieval. - this->collectActions(); - } - - Module::Module(Module const& oldModule, std::string const& newModuleName, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState) - : moduleName(newModuleName), booleanVariableToLocalIndexMap(oldModule.booleanVariableToLocalIndexMap), integerVariableToLocalIndexMap(oldModule.integerVariableToLocalIndexMap) { - LOG4CPLUS_TRACE(logger, "Start renaming " << oldModule.getName() << " to " << moduleName << "."); - - // Iterate over boolean variables and rename them. If a variable was not renamed, this is an error and an exception - // is thrown. - this->booleanVariables.reserve(oldModule.getNumberOfBooleanVariables()); - for (BooleanVariable const& booleanVariable : oldModule.booleanVariables) { - auto renamingPair = renaming.find(booleanVariable.getName()); - if (renamingPair == renaming.end()) { - LOG4CPLUS_ERROR(logger, "Boolean variable " << moduleName << "." << booleanVariable.getName() << " was not renamed."); - throw storm::exceptions::InvalidArgumentException() << "Boolean variable " << moduleName << "." << booleanVariable.getName() << " was not renamed."; - } else { - uint_fast64_t globalIndex = variableState.addBooleanVariable(renamingPair->second); - this->booleanVariables.emplace_back(booleanVariable, renamingPair->second, globalIndex, renaming, variableState); - } - } - // Now do the same for the integer variables. - this->integerVariables.reserve(oldModule.getNumberOfIntegerVariables()); - for (IntegerVariable const& integerVariable : oldModule.integerVariables) { - auto renamingPair = renaming.find(integerVariable.getName()); - if (renamingPair == renaming.end()) { - LOG4CPLUS_ERROR(logger, "Integer variable " << moduleName << "." << integerVariable.getName() << " was not renamed."); - throw storm::exceptions::InvalidArgumentException() << "Integer variable " << moduleName << "." << integerVariable.getName() << " was not renamed."; - } else { - uint_fast64_t globalIndex = variableState.addIntegerVariable(renamingPair->second); - this->integerVariables.emplace_back(integerVariable, renamingPair->second, globalIndex, renaming, variableState); - } - } - - // Now we are ready to clone all commands and rename them if requested. - this->commands.reserve(oldModule.getNumberOfCommands()); - for (Command const& command : oldModule.commands) { - this->commands.emplace_back(command, variableState.getNextGlobalCommandIndex(), renaming, variableState); - variableState.nextGlobalCommandIndex++; - } - this->collectActions(); - - LOG4CPLUS_TRACE(logger, "Finished renaming..."); - } - - uint_fast64_t Module::getNumberOfBooleanVariables() const { - return this->booleanVariables.size(); - } - - storm::ir::BooleanVariable const& Module::getBooleanVariable(uint_fast64_t index) const { - return this->booleanVariables[index]; - } - - storm::ir::BooleanVariable const& Module::getBooleanVariable(std::string const& variableName) const { - uint_fast64_t index = this->getBooleanVariableIndex(variableName); - return this->booleanVariables[index]; - } - - uint_fast64_t Module::getNumberOfIntegerVariables() const { - return this->integerVariables.size(); - } - - storm::ir::IntegerVariable const& Module::getIntegerVariable(uint_fast64_t index) const { - return this->integerVariables[index]; - } - - storm::ir::IntegerVariable const& Module::getIntegerVariable(std::string const& variableName) const { - uint_fast64_t index = this->getIntegerVariableIndex(variableName); - return this->integerVariables[index]; - } - - uint_fast64_t Module::getNumberOfCommands() const { - return this->commands.size(); - } - - uint_fast64_t Module::getBooleanVariableIndex(std::string const& variableName) const { - auto it = booleanVariableToLocalIndexMap.find(variableName); - if (it != booleanVariableToLocalIndexMap.end()) { - return it->second; - } - LOG4CPLUS_ERROR(logger, "Cannot retrieve index of unknown boolean variable " << variableName << "."); - throw storm::exceptions::InvalidArgumentException() << "Cannot retrieve index of unknown boolean variable " << variableName << "."; - } - - uint_fast64_t Module::getIntegerVariableIndex(std::string const& variableName) const { - auto it = integerVariableToLocalIndexMap.find(variableName); - if (it != integerVariableToLocalIndexMap.end()) { - return it->second; - } - LOG4CPLUS_ERROR(logger, "Cannot retrieve index of unknown integer variable " << variableName << "."); - throw storm::exceptions::InvalidArgumentException() << "Cannot retrieve index of unknown integer variable " << variableName << "."; - } - - storm::ir::Command const& Module::getCommand(uint_fast64_t index) const { - return this->commands[index]; - } - - std::string const& Module::getName() const { - return this->moduleName; - } - - std::string Module::toString() const { - std::stringstream result; - result << "module " << moduleName << std::endl; - for (auto variable : booleanVariables) { - result << "\t" << variable.toString() << std::endl; - } - for (auto variable : integerVariables) { - result << "\t" << variable.toString() << std::endl; - } - for (auto command : commands) { - result << "\t" << command.toString() << std::endl; - } - result << "endmodule" << std::endl; - return result.str(); - } - - std::set<std::string> const& Module::getActions() const { - return this->actions; - } - - bool Module::hasAction(std::string const& action) const { - auto const& actionEntry = this->actions.find(action); - if (actionEntry != this->actions.end()) { - return true; - } - return false; - } - - std::set<uint_fast64_t> const& Module::getCommandsByAction(std::string const& action) const { - auto actionsCommandSetPair = this->actionsToCommandIndexMap.find(action); - if (actionsCommandSetPair != this->actionsToCommandIndexMap.end()) { - return actionsCommandSetPair->second; - } - - LOG4CPLUS_ERROR(logger, "Action name '" << action << "' does not exist in module."); - throw storm::exceptions::OutOfRangeException() << "Action name '" << action << "' does not exist in module."; - } - - void Module::collectActions() { - // Clear the current mapping. - this->actionsToCommandIndexMap.clear(); - - // Add the mapping for all commands. - for (unsigned int id = 0; id < this->commands.size(); id++) { - std::string const& action = this->commands[id].getActionName(); - if (action != "") { - if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) { - this->actionsToCommandIndexMap.emplace(action, std::set<uint_fast64_t>()); - } - this->actionsToCommandIndexMap[action].insert(id); - this->actions.insert(action); - } - } - - // For all actions that are "in the module", but for which no command exists, we add the mapping to an empty - // set of commands. - for (auto const& action : this->actions) { - if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) { - this->actionsToCommandIndexMap[action] = std::set<uint_fast64_t>(); - } - } - } - - void Module::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) { - // First construct the new vector of commands. - std::vector<storm::ir::Command> newCommands; - for (auto const& command : commands) { - if (indexSet.find(command.getGlobalIndex()) != indexSet.end()) { - newCommands.push_back(std::move(command)); - } - } - commands = std::move(newCommands); - - // Then refresh the internal mappings. - this->collectActions(); - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/Module.h b/src/ir/Module.h deleted file mode 100644 index d9570c652..000000000 --- a/src/ir/Module.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Module.h - * - * Created on: 04.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_MODULE_H_ -#define STORM_IR_MODULE_H_ - -#include "utility/OsDetection.h" -#include <boost/container/flat_set.hpp> - -#ifdef LINUX -#include <boost/container/map.hpp> -#endif -#include <map> - -#include <set> -#include <string> -#include <vector> -#include <memory> - -#include "BooleanVariable.h" -#include "IntegerVariable.h" -#include "Command.h" -#include "expressions/VariableExpression.h" - -namespace storm { - - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - - /*! - * A class representing a module. - */ - class Module { - public: - /*! - * Default constructor. Creates an empty module. - */ - Module(); - - /*! - * Creates a module with the given name, variables and commands. - * - * @param moduleName The name of the module. - * @param booleanVariables The boolean variables defined by the module. - * @param integerVariables The integer variables defined by the module. - * @param booleanVariableToLocalIndexMap A mapping of boolean variables to local (i.e. module-local) indices. - * @param integerVariableToLocalIndexMap A mapping of integer variables to local (i.e. module-local) indices. - * @param commands The commands of the module. - */ - Module(std::string const& moduleName, std::vector<storm::ir::BooleanVariable> const& booleanVariables, - std::vector<storm::ir::IntegerVariable> const& integerVariables, - std::map<std::string, uint_fast64_t> const& booleanVariableToLocalIndexMap, - std::map<std::string, uint_fast64_t> const& integerVariableToLocalIndexMap, - std::vector<storm::ir::Command> const& commands); - - /*! - * Special copy constructor, implementing the module renaming functionality. - * This will create a new module having all identifiers renamed according to the given map. - * - * @param oldModule The module to be copied. - * @param newModuleName The name of the new module. - * @param renaming A mapping of identifiers to the new identifiers they are to be replaced with. - * @param variableState An object knowing about the variables in the system. - */ - Module(Module const& oldModule, std::string const& newModuleName, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState); - - /*! - * Retrieves the number of boolean variables in the module. - * - * @return the number of boolean variables in the module. - */ - uint_fast64_t getNumberOfBooleanVariables() const; - - /*! - * Retrieves a reference to the boolean variable with the given index. - * - * @return A reference to the boolean variable with the given index. - */ - storm::ir::BooleanVariable const& getBooleanVariable(uint_fast64_t index) const; - - /*! - * Retrieves a reference to the boolean variable with the given name. - * - * @return A reference to the boolean variable with the given name. - */ - storm::ir::BooleanVariable const& getBooleanVariable(std::string const& variableName) const; - - /*! - * Retrieves the number of integer variables in the module. - * - * @return The number of integer variables in the module. - */ - uint_fast64_t getNumberOfIntegerVariables() const; - - /*! - * Retrieves a reference to the integer variable with the given index. - * - * @return A reference to the integer variable with the given index. - */ - storm::ir::IntegerVariable const& getIntegerVariable(uint_fast64_t index) const; - - /*! - * Retrieves a reference to the boolean variable with the given name. - * - * @return A reference to the boolean variable with the given name. - */ - storm::ir::IntegerVariable const& getIntegerVariable(std::string const& variableName) const; - - /*! - * Retrieves the number of commands of this module. - * - * @return the number of commands of this module. - */ - uint_fast64_t getNumberOfCommands() const; - - /*! - * Retrieves the index of the boolean variable with the given name. - * - * @param variableName The name of the boolean variable whose index to retrieve. - * @return The index of the boolean variable with the given name. - */ - uint_fast64_t getBooleanVariableIndex(std::string const& variableName) const; - - /*! - * Retrieves the index of the integer variable with the given name. - * - * @param variableName The name of the integer variable whose index to retrieve. - * @return The index of the integer variable with the given name. - */ - uint_fast64_t getIntegerVariableIndex(std::string const& variableName) const; - - /*! - * Retrieves a reference to the command with the given index. - * - * @return A reference to the command with the given index. - */ - storm::ir::Command const& getCommand(uint_fast64_t index) const; - - /*! - * Retrieves the name of the module. - * - * @return The name of the module. - */ - std::string const& getName() const; - - /*! - * Retrieves a string representation of this module. - * - * @return a string representation of this module. - */ - std::string toString() const; - - /*! - * Retrieves the set of actions present in this module. - * - * @return the set of actions present in this module. - */ - std::set<std::string> const& getActions() const; - - /*! - * Retrieves whether or not this module contains a command labeled with the given action. - * - * @param action The action name to look for in this module. - * @return True if the module has at least one command labeled with the given action. - */ - bool hasAction(std::string const& action) const; - - /*! - * Retrieves the indices of all commands within this module that are labelled by the given action. - * - * @param action The action with which the commands have to be labelled. - * @return A set of indices of commands that are labelled with the given action. - */ - std::set<uint_fast64_t> const& getCommandsByAction(std::string const& action) const; - - /*! - * Deletes all commands with indices not in the given set from the module. - * - * @param indexSet The set of indices for which to keep the commands. - */ - void restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet); - - private: - /*! - * Computes the locally maintained mappings for fast data retrieval. - */ - void collectActions(); - - // The name of the module. - std::string moduleName; - - // A list of boolean variables. - std::vector<storm::ir::BooleanVariable> booleanVariables; - - // A list of integer variables. - std::vector<storm::ir::IntegerVariable> integerVariables; - - // A map of boolean variable names to their index. - std::map<std::string, uint_fast64_t> booleanVariableToLocalIndexMap; - - // A map of integer variable names to their index. - std::map<std::string, uint_fast64_t> integerVariableToLocalIndexMap; - - // The commands associated with the module. - std::vector<storm::ir::Command> commands; - - // The set of actions present in this module. - std::set<std::string> actions; - - // A map of actions to the set of commands labeled with this action. - std::map<std::string, std::set<uint_fast64_t>> actionsToCommandIndexMap; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_MODULE_H_ */ diff --git a/src/ir/Program.cpp b/src/ir/Program.cpp deleted file mode 100644 index 33c75c44f..000000000 --- a/src/ir/Program.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Program.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> -#include <iostream> - -#include "Program.h" -#include "exceptions/InvalidArgumentException.h" -#include "src/exceptions/OutOfRangeException.h" - -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" -extern log4cplus::Logger logger; - -namespace storm { - namespace ir { - - Program::Program() : modelType(UNDEFINED), booleanUndefinedConstantExpressions(), integerUndefinedConstantExpressions(), doubleUndefinedConstantExpressions(), modules(), rewards(), actions(), actionsToModuleIndexMap(), variableToModuleIndexMap() { - // Nothing to do here. - } - - Program::Program(ModelType modelType, - std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& booleanUndefinedConstantExpressions, - std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& integerUndefinedConstantExpressions, - std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& doubleUndefinedConstantExpressions, - std::vector<BooleanVariable> const& globalBooleanVariables, - std::vector<IntegerVariable> const& globalIntegerVariables, - std::map<std::string, uint_fast64_t> const& globalBooleanVariableToIndexMap, - std::map<std::string, uint_fast64_t> const& globalIntegerVariableToIndexMap, - std::vector<storm::ir::Module> const& modules, - std::map<std::string, storm::ir::RewardModel> const& rewards, - std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& labels) - : modelType(modelType), globalBooleanVariables(globalBooleanVariables), globalIntegerVariables(globalIntegerVariables), - globalBooleanVariableToIndexMap(globalBooleanVariableToIndexMap), globalIntegerVariableToIndexMap(globalIntegerVariableToIndexMap), - modules(modules), rewards(rewards), actionsToModuleIndexMap(), variableToModuleIndexMap() { - - // Perform a deep-copy of the maps. - for (auto const& booleanUndefinedConstant : booleanUndefinedConstantExpressions) { - this->booleanUndefinedConstantExpressions[booleanUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>(new storm::ir::expressions::BooleanConstantExpression(*booleanUndefinedConstant.second)); - } - for (auto const& integerUndefinedConstant : integerUndefinedConstantExpressions) { - this->integerUndefinedConstantExpressions[integerUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>(new storm::ir::expressions::IntegerConstantExpression(*integerUndefinedConstant.second)); - } - for (auto const& doubleUndefinedConstant : doubleUndefinedConstantExpressions) { - this->doubleUndefinedConstantExpressions[doubleUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>(new storm::ir::expressions::DoubleConstantExpression(*doubleUndefinedConstant.second)); - } - for (auto const& label : labels) { - this->labels[label.first] = label.second->clone(); - } - - // Now build the mapping from action names to module indices so that the lookup can later be performed quickly. - for (unsigned int moduleIndex = 0; moduleIndex < this->modules.size(); moduleIndex++) { - Module const& module = this->modules[moduleIndex]; - - for (auto const& action : module.getActions()) { - if (this->actionsToModuleIndexMap.count(action) == 0) { - this->actionsToModuleIndexMap[action] = std::set<uint_fast64_t>(); - } - this->actionsToModuleIndexMap[action].insert(moduleIndex); - this->actions.insert(action); - } - - // Put in the appropriate entries for the mapping from variable names to module index. - for (uint_fast64_t booleanVariableIndex = 0; booleanVariableIndex < module.getNumberOfBooleanVariables(); ++booleanVariableIndex) { - this->variableToModuleIndexMap[module.getBooleanVariable(booleanVariableIndex).getName()] = moduleIndex; - } - for (uint_fast64_t integerVariableIndex = 0; integerVariableIndex < module.getNumberOfIntegerVariables(); ++integerVariableIndex) { - this->variableToModuleIndexMap[module.getIntegerVariable(integerVariableIndex).getName()] = moduleIndex; - } - } - } - - Program::Program(Program const& otherProgram) : modelType(otherProgram.modelType), globalBooleanVariables(otherProgram.globalBooleanVariables), - globalIntegerVariables(otherProgram.globalIntegerVariables), globalBooleanVariableToIndexMap(otherProgram.globalBooleanVariableToIndexMap), - globalIntegerVariableToIndexMap(otherProgram.globalIntegerVariableToIndexMap), modules(otherProgram.modules), rewards(otherProgram.rewards), - actions(otherProgram.actions), actionsToModuleIndexMap(), variableToModuleIndexMap() { - // Perform deep-copy of the maps. - for (auto const& booleanUndefinedConstant : otherProgram.booleanUndefinedConstantExpressions) { - this->booleanUndefinedConstantExpressions[booleanUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>(new storm::ir::expressions::BooleanConstantExpression(*booleanUndefinedConstant.second)); - } - for (auto const& integerUndefinedConstant : otherProgram.integerUndefinedConstantExpressions) { - this->integerUndefinedConstantExpressions[integerUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>(new storm::ir::expressions::IntegerConstantExpression(*integerUndefinedConstant.second)); - } - for (auto const& doubleUndefinedConstant : otherProgram.doubleUndefinedConstantExpressions) { - this->doubleUndefinedConstantExpressions[doubleUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>(new storm::ir::expressions::DoubleConstantExpression(*doubleUndefinedConstant.second)); - } - for (auto const& label : otherProgram.labels) { - this->labels[label.first] = label.second->clone(); - } - } - - Program& Program::operator=(Program const& otherProgram) { - if (this != &otherProgram) { - this->modelType = otherProgram.modelType; - this->globalBooleanVariables = otherProgram.globalBooleanVariables; - this->globalIntegerVariables = otherProgram.globalIntegerVariables; - this->globalBooleanVariableToIndexMap = otherProgram.globalBooleanVariableToIndexMap; - this->globalIntegerVariableToIndexMap = otherProgram.globalIntegerVariableToIndexMap; - this->modules = otherProgram.modules; - this->rewards = otherProgram.rewards; - this->actions = otherProgram.actions; - this->actionsToModuleIndexMap = otherProgram.actionsToModuleIndexMap; - this->variableToModuleIndexMap = otherProgram.variableToModuleIndexMap; - - // Perform deep-copy of the maps. - for (auto const& booleanUndefinedConstant : otherProgram.booleanUndefinedConstantExpressions) { - this->booleanUndefinedConstantExpressions[booleanUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>(new storm::ir::expressions::BooleanConstantExpression(*booleanUndefinedConstant.second)); - } - for (auto const& integerUndefinedConstant : otherProgram.integerUndefinedConstantExpressions) { - this->integerUndefinedConstantExpressions[integerUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>(new storm::ir::expressions::IntegerConstantExpression(*integerUndefinedConstant.second)); - } - for (auto const& doubleUndefinedConstant : otherProgram.doubleUndefinedConstantExpressions) { - this->doubleUndefinedConstantExpressions[doubleUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>(new storm::ir::expressions::DoubleConstantExpression(*doubleUndefinedConstant.second)); - } - for (auto const& label : otherProgram.labels) { - this->labels[label.first] = label.second->clone(); - } - } - - return *this; - } - - Program::ModelType Program::getModelType() const { - return modelType; - } - - std::string Program::toString() const { - std::stringstream result; - switch (modelType) { - case UNDEFINED: result << "undefined"; break; - case DTMC: result << "dtmc"; break; - case CTMC: result << "ctmc"; break; - case MDP: result << "mdp"; break; - case CTMDP: result << "ctmdp"; break; - } - result << std::endl; - - for (auto const& element : booleanUndefinedConstantExpressions) { - result << "const bool " << element.second->toString() << ";" << std::endl; - } - for (auto const& element : integerUndefinedConstantExpressions) { - result << "const int " << element.second->toString() << ";" << std::endl; - } - for (auto const& element : doubleUndefinedConstantExpressions) { - result << "const double " << element.second->toString() << ";" << std::endl; - } - result << std::endl; - - for (auto const& element : globalBooleanVariables) { - result << "global " << element.toString() << std::endl; - } - for (auto const& element : globalIntegerVariables) { - result << "global " << element.toString() << std::endl; - } - result << std::endl; - - for (auto const& module : modules) { - result << module.toString() << std::endl; - } - - for (auto const& rewardModel : rewards) { - result << rewardModel.second.toString() << std::endl; - } - - for (auto const& label : labels) { - result << "label \"" << label.first << "\" = " << label.second->toString() <<";" << std::endl; - } - - return result.str(); - } - - storm::ir::BooleanVariable const& Program::getGlobalBooleanVariable(uint_fast64_t index) const { - return this->globalBooleanVariables[index]; - } - - storm::ir::IntegerVariable const& Program::getGlobalIntegerVariable(uint_fast64_t index) const { - return this->globalIntegerVariables[index]; - } - - uint_fast64_t Program::getNumberOfModules() const { - return this->modules.size(); - } - - storm::ir::Module const& Program::getModule(uint_fast64_t index) const { - return this->modules[index]; - } - - std::set<std::string> const& Program::getActions() const { - return this->actions; - } - - std::set<uint_fast64_t> const& Program::getModulesByAction(std::string const& action) const { - auto actionModuleSetPair = this->actionsToModuleIndexMap.find(action); - if (actionModuleSetPair == this->actionsToModuleIndexMap.end()) { - LOG4CPLUS_ERROR(logger, "Action name '" << action << "' does not exist."); - throw storm::exceptions::OutOfRangeException() << "Action name '" << action << "' does not exist."; - } - return actionModuleSetPair->second; - } - - uint_fast64_t Program::getModuleIndexForVariable(std::string const& variableName) const { - auto variableNameToModuleIndexPair = this->variableToModuleIndexMap.find(variableName); - if (variableNameToModuleIndexPair != this->variableToModuleIndexMap.end()) { - return variableNameToModuleIndexPair->second; - } - throw storm::exceptions::OutOfRangeException() << "Variable '" << variableName << "' does not exist."; - } - - uint_fast64_t Program::getNumberOfGlobalBooleanVariables() const { - return this->globalBooleanVariables.size(); - } - - uint_fast64_t Program::getNumberOfGlobalIntegerVariables() const { - return this->globalIntegerVariables.size(); - } - - storm::ir::RewardModel const& Program::getRewardModel(std::string const& name) const { - auto nameRewardModelPair = this->rewards.find(name); - if (nameRewardModelPair == this->rewards.end()) { - LOG4CPLUS_ERROR(logger, "Reward model '" << name << "' does not exist."); - throw storm::exceptions::OutOfRangeException() << "Reward model '" << name << "' does not exist."; - } - return nameRewardModelPair->second; - } - - std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& Program::getLabels() const { - return this->labels; - } - - bool Program::hasUndefinedBooleanConstant(std::string const& constantName) const { - return this->booleanUndefinedConstantExpressions.find(constantName) != this->booleanUndefinedConstantExpressions.end(); - } - - std::unique_ptr<storm::ir::expressions::BooleanConstantExpression> const& Program::getUndefinedBooleanConstantExpression(std::string const& constantName) const { - auto constantExpressionPair = this->booleanUndefinedConstantExpressions.find(constantName); - if (constantExpressionPair != this->booleanUndefinedConstantExpressions.end()) { - return constantExpressionPair->second; - } else { - throw storm::exceptions::InvalidArgumentException() << "Unknown undefined boolean constant " << constantName << "."; - } - } - - bool Program::hasUndefinedIntegerConstant(std::string const& constantName) const { - return this->integerUndefinedConstantExpressions.find(constantName) != this->integerUndefinedConstantExpressions.end(); - } - - std::unique_ptr<storm::ir::expressions::IntegerConstantExpression> const& Program::getUndefinedIntegerConstantExpression(std::string const& constantName) const { - auto constantExpressionPair = this->integerUndefinedConstantExpressions.find(constantName); - if (constantExpressionPair != this->integerUndefinedConstantExpressions.end()) { - return constantExpressionPair->second; - } else { - throw storm::exceptions::InvalidArgumentException() << "Unknown undefined integer constant " << constantName << "."; - } - } - - bool Program::hasUndefinedDoubleConstant(std::string const& constantName) const { - return this->doubleUndefinedConstantExpressions.find(constantName) != this->doubleUndefinedConstantExpressions.end(); - } - - std::unique_ptr<storm::ir::expressions::DoubleConstantExpression> const& Program::getUndefinedDoubleConstantExpression(std::string const& constantName) const { - auto constantExpressionPair = this->doubleUndefinedConstantExpressions.find(constantName); - if (constantExpressionPair != this->doubleUndefinedConstantExpressions.end()) { - return constantExpressionPair->second; - } else { - throw storm::exceptions::InvalidArgumentException() << "Unknown undefined double constant " << constantName << "."; - } - } - - std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& Program::getBooleanUndefinedConstantExpressionsMap() const { - return this->booleanUndefinedConstantExpressions; - } - - std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& Program::getIntegerUndefinedConstantExpressionsMap() const { - return this->integerUndefinedConstantExpressions; - } - - std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& Program::getDoubleUndefinedConstantExpressionsMap() const { - return this->doubleUndefinedConstantExpressions; - } - - uint_fast64_t Program::getGlobalIndexOfBooleanVariable(std::string const& variableName) const { - return this->globalBooleanVariableToIndexMap.at(variableName); - } - - uint_fast64_t Program::getGlobalIndexOfIntegerVariable(std::string const& variableName) const { - return this->globalIntegerVariableToIndexMap.at(variableName); - } - - void Program::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) { - for (auto& module : modules) { - module.restrictCommands(indexSet); - } - } - - } // namespace ir -} // namepsace storm diff --git a/src/ir/Program.h b/src/ir/Program.h deleted file mode 100644 index 8ce96bc87..000000000 --- a/src/ir/Program.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Program.h - * - * Created on: 04.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_PROGRAM_H_ -#define STORM_IR_PROGRAM_H_ - -#include <map> -#include <vector> -#include <memory> -#include <set> -#include <boost/container/flat_set.hpp> - -#include "expressions/BaseExpression.h" -#include "expressions/BooleanConstantExpression.h" -#include "expressions/IntegerConstantExpression.h" -#include "expressions/DoubleConstantExpression.h" -#include "Module.h" -#include "RewardModel.h" - -namespace storm { - namespace ir { - - /*! - * A class representing a program. - */ - class Program { - public: - - /*! - * An enum for the different model types. - */ - enum ModelType {UNDEFINED, DTMC, CTMC, MDP, CTMDP}; - - /*! - * Default constructor. Creates an empty program. - */ - Program(); - - /*! - * Creates a program with the given model type, undefined constants, modules, rewards and labels. - * - * @param modelType The type of the model that this program gives rise to. - * @param booleanUndefinedConstantExpressions A map of undefined boolean constants to their - * expression nodes. - * @param integerUndefinedConstantExpressions A map of undefined integer constants to their - * expression nodes. - * @param doubleUndefinedConstantExpressions A map of undefined double constants to their - * expression nodes. - * @param globalBooleanVariables A list of global boolean variables. - * @param globalIntegerVariables A list of global integer variables. - * @param globalBooleanVariableToIndexMap A mapping from global boolean variable names to the index in the - * list of global boolean variables. - * @param globalIntegerVariableToIndexMap A mapping from global integer variable names to the index in the - * list of global integer variables. - * @param modules The modules of the program. - * @param rewards The reward models of the program. - * @param labels The labels defined for this model. - */ - Program(ModelType modelType, - std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& booleanUndefinedConstantExpressions, - std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& integerUndefinedConstantExpressions, - std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& doubleUndefinedConstantExpressions, - std::vector<BooleanVariable> const& globalBooleanVariables, - std::vector<IntegerVariable> const& globalIntegerVariables, - std::map<std::string, uint_fast64_t> const& globalBooleanVariableToIndexMap, - std::map<std::string, uint_fast64_t> const& globalIntegerVariableToIndexMap, - std::vector<storm::ir::Module> const& modules, - std::map<std::string, storm::ir::RewardModel> const& rewards, - std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& labels); - - /*! - * Performs a deep-copy of the given program. - * - * @param otherProgram The program to copy. - */ - Program(Program const& otherProgram); - - /*! - * Performs a deep-copy of the given program and assigns it to the current one. - * - * @param otherProgram The program to assign. - */ - Program& operator=(Program const& otherProgram); - - /*! - * Retrieves the number of modules in the program. - * - * @return The number of modules in the program. - */ - uint_fast64_t getNumberOfModules() const; - - /*! - * Retrieves a reference to the module with the given index. - * - * @param index The index of the module to retrieve. - * @return The module with the given index. - */ - storm::ir::Module const& getModule(uint_fast64_t index) const; - - /*! - * Retrieves the model type of the model. - * - * @return The type of the model. - */ - ModelType getModelType() const; - - /*! - * Retrieves a string representation of this program. - * - * @return A string representation of this program. - */ - std::string toString() const; - - /*! - * Retrieves a reference to the global boolean variable with the given index. - * - * @return A reference to the global boolean variable with the given index. - */ - storm::ir::BooleanVariable const& getGlobalBooleanVariable(uint_fast64_t index) const; - - /*! - * Retrieves a reference to the global integer variable with the given index. - * - * @return A reference to the global integer variable with the given index. - */ - storm::ir::IntegerVariable const& getGlobalIntegerVariable(uint_fast64_t index) const; - - /*! - * Retrieves the set of actions present in this module. - * - * @return The set of actions present in this module. - */ - std::set<std::string> const& getActions() const; - - /*! - * Retrieves the indices of all modules within this program that contain commands that are labelled with the given - * action. - * - * @param action The name of the action the modules are supposed to possess. - * @return A set of indices of all matching modules. - */ - std::set<uint_fast64_t> const& getModulesByAction(std::string const& action) const; - - /*! - * Retrieves the index of the module in which the given variable name was declared. - * - * @param variableName The name of the variable to search. - * @return The index of the module in which the given variable name was declared. - */ - uint_fast64_t getModuleIndexForVariable(std::string const& variableName) const; - - /*! - * Retrieves the number of global boolean variables of the program. - * - * @return The number of global boolean variables of the program. - */ - uint_fast64_t getNumberOfGlobalBooleanVariables() const; - - /*! - * Retrieves the number of global integer variables of the program. - * - * @return The number of global integer variables of the program. - */ - uint_fast64_t getNumberOfGlobalIntegerVariables() const; - - /*! - * Retrieves the reward model with the given name. - * - * @param name The name of the reward model to return. - * @return The reward model with the given name. - */ - storm::ir::RewardModel const& getRewardModel(std::string const& name) const; - - /*! - * Retrieves all labels that are defined by the probabilitic program. - * - * @return A set of labels that are defined in the program. - */ - std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& getLabels() const; - - /*! - * Retrieves whether the given constant name is an undefined boolean constant of the program. - * - * @return True if the given constant name is an undefined boolean constant of the program. - */ - bool hasUndefinedBooleanConstant(std::string const& constantName) const; - - /*! - * Retrieves the expression associated with the given undefined boolean constant. - * - * @param constantName The name of the undefined boolean constant for which to retrieve the expression. - * @return The expression associated with the given undefined boolean constant. - */ - std::unique_ptr<storm::ir::expressions::BooleanConstantExpression> const& getUndefinedBooleanConstantExpression(std::string const& constantName) const; - - /*! - * Retrieves whether the given constant name is an undefined integer constant of the program. - * - * @return True if the given constant name is an undefined integer constant of the program. - */ - bool hasUndefinedIntegerConstant(std::string const& constantName) const; - - /*! - * Retrieves the expression associated with the given undefined integer constant. - * - * @param constantName The name of the undefined integer constant for which to retrieve the expression. - * @return The expression associated with the given undefined integer constant. - */ - std::unique_ptr<storm::ir::expressions::IntegerConstantExpression> const& getUndefinedIntegerConstantExpression(std::string const& constantName) const; - - /*! - * Retrieves whether the given constant name is an undefined double constant of the program. - * - * @return True if the given constant name is an undefined double constant of the program. - */ - bool hasUndefinedDoubleConstant(std::string const& constantName) const; - - /*! - * Retrieves the expression associated with the given undefined double constant. - * - * @param constantName The name of the undefined double constant for which to retrieve the expression. - * @return The expression associated with the given undefined double constant. - */ - std::unique_ptr<storm::ir::expressions::DoubleConstantExpression> const& getUndefinedDoubleConstantExpression(std::string const& constantName) const; - - /*! - * Retrieves the mapping of undefined boolean constant names to their expression objects. - * - * @return The mapping of undefined boolean constant names to their expression objects. - */ - std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& getBooleanUndefinedConstantExpressionsMap() const; - - /*! - * Retrieves the mapping of undefined integer constant names to their expression objects. - * - * @return The mapping of undefined integer constant names to their expression objects. - */ - std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& getIntegerUndefinedConstantExpressionsMap() const; - - /*! - * Retrieves the mapping of undefined double constant names to their expression objects. - * - * @return The mapping of undefined double constant names to their expression objects. - */ - std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& getDoubleUndefinedConstantExpressionsMap() const; - - /*! - * Retrieves the global index of the given boolean variable. - * - * @param variableName The name of the boolean variable whose index to retrieve. - */ - uint_fast64_t getGlobalIndexOfBooleanVariable(std::string const& variableName) const; - - /*! - * Retrieves the global index of the integer boolean variable. - * - * @param variableName The name of the integer variable whose index to retrieve. - */ - uint_fast64_t getGlobalIndexOfIntegerVariable(std::string const& variableName) const; - - /*! - * Deletes all commands with indices not in the given set from the program. - * - * @param indexSet The set of indices for which to keep the commands. - */ - void restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet); - private: - // The type of the model. - ModelType modelType; - - // A map of undefined boolean constants to their expression nodes. - std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> booleanUndefinedConstantExpressions; - - // A map of undefined integer constants to their expressions nodes. - std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> integerUndefinedConstantExpressions; - - // A map of undefined double constants to their expressions nodes. - std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> doubleUndefinedConstantExpressions; - - // A list of global boolean variables. - std::vector<BooleanVariable> globalBooleanVariables; - - // A list of global integer variables. - std::vector<IntegerVariable> globalIntegerVariables; - - // A mapping from global boolean variable names to their indices. - std::map<std::string, uint_fast64_t> globalBooleanVariableToIndexMap; - - // A mapping from global integer variable names to their indices. - std::map<std::string, uint_fast64_t> globalIntegerVariableToIndexMap; - - // The modules associated with the program. - std::vector<storm::ir::Module> modules; - - // The reward models associated with the program. - std::map<std::string, storm::ir::RewardModel> rewards; - - // The labels that are defined for this model. - std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> labels; - - // The set of actions present in this program. - std::set<std::string> actions; - - // A map of actions to the set of modules containing commands labelled with this action. - std::map<std::string, std::set<uint_fast64_t>> actionsToModuleIndexMap; - - // A mapping from variable names to the modules in which they were declared. - std::map<std::string, uint_fast64_t> variableToModuleIndexMap; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_PROGRAM_H_ */ diff --git a/src/ir/RewardModel.cpp b/src/ir/RewardModel.cpp deleted file mode 100644 index 9d6a79ed3..000000000 --- a/src/ir/RewardModel.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * RewardModel.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "RewardModel.h" - -namespace storm { - namespace ir { - - RewardModel::RewardModel() : rewardModelName(), stateRewards(), transitionRewards() { - // Nothing to do here. - } - - RewardModel::RewardModel(std::string const& rewardModelName, std::vector<storm::ir::StateReward> const& stateRewards, std::vector<storm::ir::TransitionReward> const& transitionRewards) : rewardModelName(rewardModelName), stateRewards(stateRewards), transitionRewards(transitionRewards) { - // Nothing to do here. - } - - std::string RewardModel::toString() const { - std::stringstream result; - result << "rewards \"" << rewardModelName << "\"" << std::endl; - for (auto const& reward : stateRewards) { - result << reward.toString() << std::endl; - } - for (auto const& reward : transitionRewards) { - result << reward.toString() << std::endl; - } - result << "endrewards" << std::endl; - return result.str(); - } - - bool RewardModel::hasStateRewards() const { - return this->stateRewards.size() > 0; - } - - std::vector<storm::ir::StateReward> const& RewardModel::getStateRewards() const { - return this->stateRewards; - } - - bool RewardModel::hasTransitionRewards() const { - return this->transitionRewards.size() > 0; - } - - std::vector<storm::ir::TransitionReward> const& RewardModel::getTransitionRewards() const { - return this->transitionRewards; - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/RewardModel.h b/src/ir/RewardModel.h deleted file mode 100644 index 827248810..000000000 --- a/src/ir/RewardModel.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * RewardModel.h - * - * Created on: 04.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_REWARDMODEL_H_ -#define STORM_IR_REWARDMODEL_H_ - -#include <string> -#include <vector> - -#include "StateReward.h" -#include "TransitionReward.h" - -namespace storm { - namespace ir { - - /*! - * A class representing a reward model. - */ - class RewardModel { - public: - /*! - * Default constructor. Creates an empty reward model. - */ - RewardModel(); - - /*! - * Creates a reward module with the given name, state and transition rewards. - * - * @param rewardModelName The name of the reward model. - * @param stateRewards A vector of state-based rewards. - * @param transitionRewards A vector of transition-based rewards. - */ - RewardModel(std::string const& rewardModelName, std::vector<storm::ir::StateReward> const& stateRewards, std::vector<storm::ir::TransitionReward> const& transitionRewards); - - /*! - * Retrieves a string representation of this reward model. - * - * @return a string representation of this reward model. - */ - std::string toString() const; - - /*! - * Check, if there are any state rewards. - * - * @return True, iff there are any state rewards. - */ - bool hasStateRewards() const; - - /*! - * Retrieves a vector of state rewards associated with this reward model. - * - * @return A vector containing the state rewards associated with this reward model. - */ - std::vector<storm::ir::StateReward> const& getStateRewards() const; - - /*! - * Check, if there are any transition rewards. - * - * @return True, iff there are any transition rewards associated with this reward model. - */ - bool hasTransitionRewards() const; - - /*! - * Retrieves a vector of transition rewards associated with this reward model. - * - * @return A vector of transition rewards associated with this reward model. - */ - std::vector<storm::ir::TransitionReward> const& getTransitionRewards() const; - - private: - // The name of the reward model. - std::string rewardModelName; - - // The state-based rewards associated with this reward model. - std::vector<storm::ir::StateReward> stateRewards; - - // The transition-based rewards associated with this reward model. - std::vector<storm::ir::TransitionReward> transitionRewards; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_REWARDMODEL_H_ */ diff --git a/src/ir/StateReward.cpp b/src/ir/StateReward.cpp deleted file mode 100644 index ff3c815ce..000000000 --- a/src/ir/StateReward.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * StateReward.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "StateReward.h" - -namespace storm { - namespace ir { - - StateReward::StateReward() : statePredicate(), rewardValue() { - // Nothing to do here. - } - - StateReward::StateReward(std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue) : statePredicate(std::move(statePredicate)), rewardValue(std::move(rewardValue)) { - // Nothing to do here. - } - - StateReward::StateReward(StateReward const& otherReward) { - if (otherReward.statePredicate != nullptr) { - statePredicate = otherReward.statePredicate->clone(); - } - if (otherReward.rewardValue != nullptr) { - rewardValue = otherReward.rewardValue->clone(); - } - } - - StateReward& StateReward::operator=(StateReward const& otherReward) { - if (this != & otherReward) { - if (otherReward.statePredicate != nullptr) { - this->statePredicate = otherReward.statePredicate->clone(); - } - if (otherReward.rewardValue != nullptr) { - this->rewardValue = otherReward.rewardValue->clone(); - } - } - - return *this; - } - - std::string StateReward::toString() const { - std::stringstream result; - result << "\t" << statePredicate->toString() << ": " << rewardValue->toString() << ";"; - return result.str(); - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& StateReward::getStatePredicate() const { - return this->statePredicate; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& StateReward::getRewardValue() const { - return this->rewardValue; - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/StateReward.h b/src/ir/StateReward.h deleted file mode 100644 index 117544d6d..000000000 --- a/src/ir/StateReward.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * StateReward.h - * - * Created on: Jan 10, 2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_STATEREWARD_H_ -#define STORM_IR_STATEREWARD_H_ - -#include <memory> - -#include "expressions/BaseExpression.h" - -namespace storm { - namespace ir { - - /*! - * A class representing a state reward. - */ - class StateReward { - public: - /*! - * Default constructor. Creates an empty state reward. - */ - StateReward(); - - /*! - * Creates a state reward for the states satisfying the given expression with the value given - * by a second expression. - * - * @param statePredicate The predicate that states earning this state-based reward need to - * satisfy. - * @param rewardValue An expression specifying the values of the rewards to attach to the - * states. - */ - StateReward(std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue); - - /*! - * Performs a deep-copy of the given reward. - * - * @param otherReward The reward to copy. - */ - StateReward(StateReward const& otherReward); - - /*! - * Performs a deep-copy of the given reward and assigns it to the current one. - * - * @param otherReward The reward to assign. - */ - StateReward& operator=(StateReward const& otherReward); - - /*! - * Retrieves a string representation of this state reward. - * - * @return A string representation of this state reward. - */ - std::string toString() const; - - /*! - * Retrieves the state predicate that is associated with this state reward. - * - * @return The state predicate that is associated with this state reward. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getStatePredicate() const; - - /*! - * Retrieves the reward value associated with this state reward. - * - * @return The reward value associated with this state reward. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getRewardValue() const; - - private: - // The predicate that characterizes the states that obtain this reward. - std::unique_ptr<storm::ir::expressions::BaseExpression> statePredicate; - - // The expression that specifies the value of the reward obtained. - std::unique_ptr<storm::ir::expressions::BaseExpression> rewardValue; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_STATEREWARD_H_ */ diff --git a/src/ir/TransitionReward.cpp b/src/ir/TransitionReward.cpp deleted file mode 100644 index bd9664529..000000000 --- a/src/ir/TransitionReward.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * TransitionReward.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "TransitionReward.h" - -namespace storm { - namespace ir { - - TransitionReward::TransitionReward() : commandName(), statePredicate(), rewardValue() { - // Nothing to do here. - } - - TransitionReward::TransitionReward(std::string const& commandName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue) : commandName(commandName), statePredicate(std::move(statePredicate)), rewardValue(std::move(rewardValue)) { - // Nothing to do here. - } - - TransitionReward::TransitionReward(TransitionReward const& otherReward) : commandName(otherReward.commandName), statePredicate(), rewardValue() { - if (otherReward.statePredicate != nullptr) { - statePredicate = otherReward.statePredicate->clone(); - } - if (otherReward.rewardValue != nullptr) { - rewardValue = otherReward.rewardValue->clone(); - } - } - - TransitionReward& TransitionReward::operator=(TransitionReward const& otherReward) { - if (this != &otherReward) { - this->commandName = otherReward.commandName; - if (otherReward.statePredicate != nullptr) { - this->statePredicate = otherReward.statePredicate->clone(); - } - if (otherReward.rewardValue != nullptr) { - this->rewardValue = otherReward.rewardValue->clone(); - } - } - - return *this; - } - - std::string TransitionReward::toString() const { - std::stringstream result; - result << "\t[" << commandName << "] " << statePredicate->toString() << ": " << rewardValue->toString() << ";"; - return result.str(); - } - - std::string const& TransitionReward::getActionName() const { - return this->commandName; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& TransitionReward::getStatePredicate() const { - return this->statePredicate; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& TransitionReward::getRewardValue() const { - return this->rewardValue; - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/TransitionReward.h b/src/ir/TransitionReward.h deleted file mode 100644 index 298d17024..000000000 --- a/src/ir/TransitionReward.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * TransitionReward.h - * - * Created on: Jan 10, 2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_TRANSITIONREWARD_H_ -#define STORM_IR_TRANSITIONREWARD_H_ - -#include <memory> - -#include "expressions/BaseExpression.h" - -namespace storm { - -namespace ir { - -/*! - * A class representing a transition reward. - */ -class TransitionReward { -public: - /*! - * Default constructor. Creates an empty transition reward. - */ - TransitionReward(); - - /*! - * Creates a transition reward for the transitions with the given name emanating from states - * satisfying the given expression with the value given by another expression. - * - * @param commandName The name of the command that obtains this reward. - * @param statePredicate The predicate that needs to hold before taking a transition with the - * previously specified name in order to obtain the reward. - * @param rewardValue An expression specifying the values of the rewards to attach to the - * transitions. - */ - TransitionReward(std::string const& commandName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue); - - /*! - * Performs a deep-copy of the given transition reward. - * - * @param otherReward The transition reward to copy. - */ - TransitionReward(TransitionReward const& otherReward); - - /*! - * Performs a deep-copy of the given transition reward and assigns it to the current one. - * - * @param otherReward The reward to assign. - */ - TransitionReward& operator=(TransitionReward const& otherReward); - - /*! - * Retrieves a string representation of this transition reward. - * - * @return A string representation of this transition reward. - */ - std::string toString() const; - - /*! - * Retrieves the action name that is associated with this transition reward. - * - * @return The action name that is associated with this transition reward. - */ - std::string const& getActionName() const; - - /*! - * Retrieves the state predicate that is associated with this state reward. - * - * @return The state predicate that is associated with this state reward. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getStatePredicate() const; - - /*! - * Retrieves the reward value associated with this state reward. - * - * @return The reward value associated with this state reward. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getRewardValue() const; - -private: - // The name of the command this transition-based reward is attached to. - std::string commandName; - - // A predicate that needs to be satisfied by states for the reward to be obtained (by taking - // a corresponding command transition). - std::unique_ptr<storm::ir::expressions::BaseExpression> statePredicate; - - // The expression specifying the value of the reward obtained along the transitions. - std::unique_ptr<storm::ir::expressions::BaseExpression> rewardValue; -}; - -} // namespace ir - -} // namespace storm - -#endif /* STORM_IR_TRANSITIONREWARD_H_ */ diff --git a/src/ir/Update.cpp b/src/ir/Update.cpp deleted file mode 100644 index aac7b3ca0..000000000 --- a/src/ir/Update.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Update.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "Update.h" -#include "src/parser/prismparser/VariableState.h" -#include "src/exceptions/OutOfRangeException.h" - -namespace storm { - namespace ir { - - Update::Update() : likelihoodExpression(), booleanAssignments(), integerAssignments(), globalIndex() { - // Nothing to do here. - } - - Update::Update(uint_fast64_t globalIndex, std::unique_ptr<storm::ir::expressions::BaseExpression>&& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments) - : likelihoodExpression(std::move(likelihoodExpression)), booleanAssignments(booleanAssignments), integerAssignments(integerAssignments), globalIndex(globalIndex) { - // Nothing to do here. - } - - Update::Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState) : globalIndex(newGlobalIndex) { - for (auto const& variableAssignmentPair : update.booleanAssignments) { - if (renaming.count(variableAssignmentPair.first) > 0) { - this->booleanAssignments[renaming.at(variableAssignmentPair.first)] = Assignment(variableAssignmentPair.second, renaming, variableState); - } else { - this->booleanAssignments[variableAssignmentPair.first] = Assignment(variableAssignmentPair.second, renaming, variableState); - } - } - for (auto const& variableAssignmentPair : update.integerAssignments) { - if (renaming.count(variableAssignmentPair.first) > 0) { - this->integerAssignments[renaming.at(variableAssignmentPair.first)] = Assignment(variableAssignmentPair.second, renaming, variableState); - } else { - this->integerAssignments[variableAssignmentPair.first] = Assignment(variableAssignmentPair.second, renaming, variableState); - } - } - this->likelihoodExpression = update.likelihoodExpression->clone(renaming, variableState); - } - - Update::Update(Update const& otherUpdate) : likelihoodExpression(), booleanAssignments(otherUpdate.booleanAssignments), integerAssignments(otherUpdate.integerAssignments), globalIndex(otherUpdate.globalIndex) { - if (otherUpdate.likelihoodExpression != nullptr) { - likelihoodExpression = otherUpdate.likelihoodExpression->clone(); - } - } - - Update& Update::operator=(Update const& otherUpdate) { - if (this != &otherUpdate) { - if (otherUpdate.likelihoodExpression != nullptr) { - this->likelihoodExpression = otherUpdate.likelihoodExpression->clone(); - } - this->booleanAssignments = otherUpdate.booleanAssignments; - this->integerAssignments = otherUpdate.integerAssignments; - this->globalIndex = otherUpdate.globalIndex; - } - - return *this; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& Update::getLikelihoodExpression() const { - return likelihoodExpression; - } - - uint_fast64_t Update::getNumberOfBooleanAssignments() const { - return booleanAssignments.size(); - } - - uint_fast64_t Update::getNumberOfIntegerAssignments() const { - return integerAssignments.size(); - } - - std::map<std::string, storm::ir::Assignment> const& Update::getBooleanAssignments() const { - return booleanAssignments; - } - - std::map<std::string, storm::ir::Assignment> const& Update::getIntegerAssignments() const { - return integerAssignments; - } - - storm::ir::Assignment const& Update::getBooleanAssignment(std::string const& variableName) const { - auto variableAssignmentPair = booleanAssignments.find(variableName); - if (variableAssignmentPair == booleanAssignments.end()) { - throw storm::exceptions::OutOfRangeException() << "Cannot find boolean assignment for variable '" - << variableName << "' in update " << this->toString() << "."; - } - - return variableAssignmentPair->second; - } - - storm::ir::Assignment const& Update::getIntegerAssignment(std::string const& variableName) const { - auto variableAssignmentPair = integerAssignments.find(variableName); - if (variableAssignmentPair == integerAssignments.end()) { - throw storm::exceptions::OutOfRangeException() << "Cannot find integer assignment for variable '" - << variableName << "' in update " << this->toString() << "."; - } - - return variableAssignmentPair->second; - } - - uint_fast64_t Update::getGlobalIndex() const { - return this->globalIndex; - } - - std::string Update::toString() const { - std::stringstream result; - result << likelihoodExpression->toString() << " : "; - uint_fast64_t i = 0; - for (auto const& assignment : booleanAssignments) { - result << assignment.second.toString(); - if (i < booleanAssignments.size() - 1 || integerAssignments.size() > 0) { - result << " & "; - } - ++i; - } - i = 0; - for (auto const& assignment : integerAssignments) { - result << assignment.second.toString(); - if (i < integerAssignments.size() - 1) { - result << " & "; - } - ++i; - } - return result.str(); - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/Update.h b/src/ir/Update.h deleted file mode 100644 index 07b9a7d24..000000000 --- a/src/ir/Update.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Update.h - * - * Created on: 06.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_UPDATE_H_ -#define STORM_IR_UPDATE_H_ - -#include <map> -#include <memory> - -#include "expressions/BaseExpression.h" -#include "Assignment.h" - -namespace storm { - - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - - /*! - * A class representing an update of a command. - */ - class Update { - public: - /*! - * Default constructor. Creates an empty update. - */ - Update(); - - /*! - * Creates an update with the given expression specifying the likelihood and the mapping of - * variable to their assignments. - * - * @param globalIndex The global index of the update. - * @param likelihoodExpression An expression specifying the likelihood of this update. - * @param assignments A map of variable names to their assignments. - */ - Update(uint_fast64_t globalIndex, std::unique_ptr<storm::ir::expressions::BaseExpression>&& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments); - - /*! - * Creates a copy of the given update and performs the provided renaming. - * - * @param update The update that is to be copied. - * @param newGlobalIndex The global index of the resulting update. - * @param renaming A mapping from names that are to be renamed to the names they are to be - * replaced with. - * @param variableState An object knowing about the variables in the system. - */ - Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState); - - /*! - * Peforms a deep-copy of the given update. - * - * @param otherUpdate The update to copy. - */ - Update(Update const& otherUpdate); - - /*! - * Performs a deep-copy of the given update and assigns it to the current one. - * - * @param otherUpdate The update to assign. - */ - Update& operator=(Update const& otherUpdate); - - /*! - * Retrieves the expression for the likelihood of this update. - * - * @return The expression for the likelihood of this update. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getLikelihoodExpression() const; - - /*! - * Retrieves the number of boolean assignments associated with this update. - * - * @return The number of boolean assignments associated with this update. - */ - uint_fast64_t getNumberOfBooleanAssignments() const; - - /*! - * Retrieves the number of integer assignments associated with this update. - * - * @return The number of integer assignments associated with this update. - */ - uint_fast64_t getNumberOfIntegerAssignments() const; - - /*! - * Retrieves a reference to the map of boolean variable names to their respective assignments. - * - * @return A reference to the map of boolean variable names to their respective assignments. - */ - std::map<std::string, storm::ir::Assignment> const& getBooleanAssignments() const; - - /*! - * Retrieves a reference to the map of integer variable names to their respective assignments. - * - * @return A reference to the map of integer variable names to their respective assignments. - */ - std::map<std::string, storm::ir::Assignment> const& getIntegerAssignments() const; - - /*! - * Retrieves a reference to the assignment for the boolean variable with the given name. - * - * @return A reference to the assignment for the boolean variable with the given name. - */ - storm::ir::Assignment const& getBooleanAssignment(std::string const& variableName) const; - - /*! - * Retrieves a reference to the assignment for the integer variable with the given name. - * - * @return A reference to the assignment for the integer variable with the given name. - */ - storm::ir::Assignment const& getIntegerAssignment(std::string const& variableName) const; - - /*! - * Retrieves the global index of the update, that is, a unique index over all modules. - * - * @return The global index of the update. - */ - uint_fast64_t getGlobalIndex() const; - - /*! - * Retrieves a string representation of this update. - * - * @return A string representation of this update. - */ - std::string toString() const; - - private: - // An expression specifying the likelihood of taking this update. - std::unique_ptr<storm::ir::expressions::BaseExpression> likelihoodExpression; - - // A mapping of boolean variable names to their assignments in this update. - std::map<std::string, storm::ir::Assignment> booleanAssignments; - - // A mapping of integer variable names to their assignments in this update. - std::map<std::string, storm::ir::Assignment> integerAssignments; - - // The global index of the update. - uint_fast64_t globalIndex; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_UPDATE_H_ */ diff --git a/src/ir/Variable.cpp b/src/ir/Variable.cpp deleted file mode 100644 index 83cb2a33a..000000000 --- a/src/ir/Variable.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Variable.cpp - * - * Created on: 12.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> -#include <map> -#include <iostream> - -#include "Variable.h" -#include "src/parser/prismparser/VariableState.h" - -namespace storm { - namespace ir { - - Variable::Variable() : localIndex(0), globalIndex(0), variableName(), initialValue() { - // Nothing to do here. - } - - Variable::Variable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue) - : localIndex(localIndex), globalIndex(globalIndex), variableName(variableName), initialValue(std::move(initialValue)) { - // Nothing to do here. - } - - Variable::Variable(Variable const& otherVariable) : localIndex(otherVariable.localIndex), globalIndex(otherVariable.globalIndex), variableName(otherVariable.variableName), initialValue() { - if (otherVariable.initialValue != nullptr) { - initialValue = otherVariable.initialValue->clone(); - } - } - - Variable::Variable(Variable const& var, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) - : localIndex(var.getLocalIndex()), globalIndex(newGlobalIndex), variableName(newName), initialValue() { - if (var.initialValue != nullptr) { - this->initialValue = var.initialValue->clone(renaming, variableState); - } - } - - Variable& Variable::operator=(Variable const& otherVariable) { - if (this != &otherVariable) { - this->localIndex = otherVariable.localIndex; - this->globalIndex = otherVariable.globalIndex; - this->variableName = otherVariable.variableName; - if (otherVariable.initialValue != nullptr) { - this->initialValue = otherVariable.initialValue->clone(); - } - } - - return *this; - } - - std::string const& Variable::getName() const { - return variableName; - } - - uint_fast64_t Variable::getGlobalIndex() const { - return globalIndex; - } - - uint_fast64_t Variable::getLocalIndex() const { - return localIndex; - } - - std::unique_ptr<storm::ir::expressions::BaseExpression> const& Variable::getInitialValue() const { - return initialValue; - } - - void Variable::setInitialValue(std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue) { - this->initialValue = std::move(initialValue); - } - - } // namespace ir -} // namespace storm diff --git a/src/ir/Variable.h b/src/ir/Variable.h deleted file mode 100644 index 53b2f3b98..000000000 --- a/src/ir/Variable.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Variable.h - * - * Created on: 06.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_VARIABLE_H_ -#define STORM_IR_VARIABLE_H_ - -#include <string> -#include <memory> - -#include "expressions/BaseExpression.h" - -namespace storm { - - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - - /*! - * A class representing a untyped variable. - */ - class Variable { - public: - /*! - * Default constructor. Creates an unnamed, untyped variable without initial value. - */ - Variable(); - - /*! - * Creates an untyped variable with the given name and initial value. - * - * @param localIndex A module-local index for the variable. - * @param globalIndex A globally unique (among the variables of equal type) index for the variable. - * @param variableName the name of the variable. - * @param initialValue the expression that defines the initial value of the variable. - */ - Variable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue = nullptr); - - /*! - * Creates a copy of the given variable and performs the provided renaming. - * - * @param oldVariable The variable to copy. - * @param newName New name of this variable. - * @param newGlobalIndex The new global index of the variable. - * @param renaming A mapping from names that are to be renamed to the names they are to be - * replaced with. - * @param variableState An object knowing about the variables in the system. - */ - Variable(Variable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState); - - /*! - * Creates a deep-copy of the given variable. - * - * @param otherVariable The variable to copy. - */ - Variable(Variable const& otherVariable); - - /*! - * Creates a deep-copy of the given variable and assigns it to the current one. - */ - Variable& operator=(Variable const& otherVariable); - - /*! - * Retrieves the name of the variable. - * - * @return The name of the variable. - */ - std::string const& getName() const; - - /*! - * Retrieves the global index of the variable, i.e. the index in all variables of equal type - * of all modules. - * - * @return The global index of the variable. - */ - uint_fast64_t getGlobalIndex() const; - - /*! - * Retrieves the global index of the variable, i.e. the index in all variables of equal type in - * the same module. - * - * @return The local index of the variable. - */ - uint_fast64_t getLocalIndex() const; - - /*! - * Retrieves the expression defining the initial value of the variable. - * - * @return The expression defining the initial value of the variable. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> const& getInitialValue() const; - - /*! - * Sets the initial value to the given expression. - * - * @param initialValue The new initial value. - */ - void setInitialValue(std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue); - - private: - // A unique (among the variables of equal type) index for the variable inside its module. - uint_fast64_t localIndex; - - // A unique (among the variables of equal type) index for the variable over all modules. - uint_fast64_t globalIndex; - - // The name of the variable. - std::string variableName; - - // The expression defining the initial value of the variable. - std::unique_ptr<storm::ir::expressions::BaseExpression> initialValue; - }; - - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_VARIABLE_H_ */ diff --git a/src/ir/expressions/BaseExpression.cpp b/src/ir/expressions/BaseExpression.cpp deleted file mode 100644 index 66771d6b0..000000000 --- a/src/ir/expressions/BaseExpression.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * BaseExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include "BaseExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - BaseExpression::BaseExpression() : type(undefined) { - // Nothing to do here. - } - - BaseExpression::BaseExpression(ReturnType type) : type(type) { - // Nothing to do here. - } - - BaseExpression::BaseExpression(BaseExpression const& baseExpression) : type(baseExpression.type) { - // Nothing to do here. - } - - BaseExpression::~BaseExpression() { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> BaseExpression::substitute(std::unique_ptr<BaseExpression>&& expression, std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) { - BaseExpression* result = expression->performSubstitution(substitution); - - if (result != expression.get()) { - return std::unique_ptr<BaseExpression>(result); - } else { - return std::move(expression); - } - } - - int_fast64_t BaseExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (type != int_) { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression of type '" - << this->getTypeName() << "' as 'int'."; - } - throw storm::exceptions::NotImplementedException() << "Cannot evaluate expression of type '" - << this->getTypeName() << " because evaluation implementation is missing."; - } - - bool BaseExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (type != bool_) { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression of type '" - << this->getTypeName() << "' as 'bool'."; - } - throw storm::exceptions::NotImplementedException() << "Cannot evaluate expression of type '" - << this->getTypeName() << " because evaluation implementation is missing."; - } - - double BaseExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (type != double_ && type != int_) { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression of type '" - << this->getTypeName() << "' as 'double'."; - } - throw storm::exceptions::NotImplementedException() << "Cannot evaluate expression of type '" - << this->getTypeName() << " because evaluation implementation is missing."; - } - - std::string BaseExpression::getTypeName() const { - switch(type) { - case bool_: return std::string("bool"); - case int_: return std::string("int"); - case double_: return std::string("double"); - default: return std::string("undefined"); - } - } - - BaseExpression::ReturnType BaseExpression::getType() const { - return type; - } - - BaseExpression* BaseExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) { - return this; - } - - } // namespace expressions - } // namespace ir -} // namespace storm diff --git a/src/ir/expressions/BaseExpression.h b/src/ir/expressions/BaseExpression.h deleted file mode 100644 index 948ed9d88..000000000 --- a/src/ir/expressions/BaseExpression.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * BaseExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_BASEEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_BASEEXPRESSION_H_ - -#include <string> -#include <vector> -#include <map> -#include <memory> - -#include "src/exceptions/ExpressionEvaluationException.h" -#include "src/exceptions/NotImplementedException.h" -#include "ExpressionVisitor.h" - -namespace storm { - - // Forward-declare VariableState. - namespace parser { - namespace prism { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - namespace expressions { - - /*! - * The base class for all expressions. - */ - class BaseExpression { - public: - // Forward declare friend classes to allow access to substitute. - friend class BinaryExpression; - friend class UnaryExpression; - - /*! - * Each node in an expression tree has a uniquely defined type from this enum. - */ - enum ReturnType {undefined, bool_, int_, double_}; - - /*! - * Creates an expression with undefined type. - */ - BaseExpression(); - - /*! - * Creates an expression with the given type. - * - * @param type The type of the expression. - */ - BaseExpression(ReturnType type); - - /*! - * Copy-constructs from the given expression. - * - * @param baseExpression The expression to copy. - */ - BaseExpression(BaseExpression const& baseExpression); - - /*! - * Destructor. - */ - virtual ~BaseExpression(); - - /*! - * Performes a deep-copy of the expression. - * - * @return A deep-copy of the expression. - */ - virtual std::unique_ptr<BaseExpression> clone() const = 0; - - /*! - * Copies the expression tree underneath (including) the current node and performs the provided renaming. - * - * @param renaming A mapping from identifier names to strings they are to be replaced with. - * @param variableState An object knowing about the global variable state. - */ - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const = 0; - - /*! - * Performs the given substitution by replacing each variable in the given expression that is a key in - * the map by a copy of the mapped expression. - * - * @param expression The expression in which to perform the substitution. - * @param substitution The substitution to apply. - * @return The resulting expression. - */ - static std::unique_ptr<BaseExpression> substitute(std::unique_ptr<BaseExpression>&& expression, std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution); - - /*! - * Retrieves the value of the expression as an integer given the provided variable valuation. - * - * @param variableValues The variable valuation under which to evaluate the expression. If set to null, - * constant expressions can be evaluated without variable values. However, upon encountering a variable - * expression an expression is thrown, because evaluation is impossible without the variable values then. - * @return The value of the expression as an integer. - */ - virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const; - - /*! - * Retrieves the value of the expression as a boolean given the provided variable valuation. - * - * @param variableValues The variable valuation under which to evaluate the expression. If set to null, - * constant expressions can be evaluated without variable values. However, upon encountering a variable - * expression an expression is thrown, because evaluation is impossible without the variable values then. - * @return The value of the expression as a boolean. - */ - virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const; - - /*! - * Retrieves the value of the expression as a double given the provided variable valuation. - * - * @param variableValues The variable valuation under which to evaluate the expression. If set to null, - * constant expressions can be evaluated without variable values. However, upon encountering a variable - * expression an expression is thrown, because evaluation is impossible without the variable values then. - * @return The value of the expression as a double. - */ - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const; - - /*! - * Acceptor method for visitor pattern. - * - * @param visitor The visitor that is supposed to visit each node of the expression tree. - */ - virtual void accept(ExpressionVisitor* visitor) = 0; - - /*! - * Retrieves a string representation of the expression tree underneath the current node. - * - * @return A string representation of the expression tree underneath the current node. - */ - virtual std::string toString() const = 0; - - /*! - * Retrieves a string representation of the type to which this node evaluates. - * - * @return A string representation of the type to which this node evaluates. - */ - std::string getTypeName() const; - - /*! - * Retrieves the type to which the node evaluates. - * - * @return The type to which the node evaluates. - */ - ReturnType getType() const; - - protected: - /*! - * Performs the given substitution on the expression, i.e. replaces all variables whose names are keys - * of the map by a copy of the expression they are associated with in the map. This is intended as a helper - * function for substitute. - * - * @param substitution The substitution to perform - */ - virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution); - - private: - // The type to which this node evaluates. - ReturnType type; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_BASEEXPRESSION_H_ */ diff --git a/src/ir/expressions/BinaryBooleanFunctionExpression.cpp b/src/ir/expressions/BinaryBooleanFunctionExpression.cpp deleted file mode 100644 index 83cb1d82f..000000000 --- a/src/ir/expressions/BinaryBooleanFunctionExpression.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * BinaryBooleanFunctionExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "BinaryBooleanFunctionExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - BinaryBooleanFunctionExpression::BinaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType) - : BinaryExpression(bool_, std::move(left), std::move(right)), functionType(functionType) { - // Nothing to do here. - } - - BinaryBooleanFunctionExpression::BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression const& binaryBooleanFunctionExpression) - : BinaryExpression(binaryBooleanFunctionExpression), functionType(binaryBooleanFunctionExpression.functionType) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> BinaryBooleanFunctionExpression::clone() const { - return std::unique_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(this->getLeft()->clone(), this->getRight()->clone(), functionType)); - } - - std::unique_ptr<BaseExpression> BinaryBooleanFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(this->getLeft()->clone(renaming, variableState), this->getRight()->clone(renaming, variableState), this->functionType)); - } - - bool BinaryBooleanFunctionExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - bool resultLeft = this->getLeft()->getValueAsBool(variableValues); - bool resultRight = this->getRight()->getValueAsBool(variableValues); - switch(functionType) { - case AND: return resultLeft & resultRight; break; - case OR: return resultLeft | resultRight; break; - default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Unknown boolean binary operator: '" << functionType << "'."; - } - } - - BinaryBooleanFunctionExpression::FunctionType BinaryBooleanFunctionExpression::getFunctionType() const { - return functionType; - } - - void BinaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string BinaryBooleanFunctionExpression::toString() const { - std::stringstream result; - result << "(" << this->getLeft()->toString(); - switch (functionType) { - case AND: result << " & "; break; - case OR: result << " | "; break; - } - result << this->getRight()->toString() << ")"; - - return result.str(); - } - - } // namespace expressions - } // namespace ir -} // namespace storm diff --git a/src/ir/expressions/BinaryBooleanFunctionExpression.h b/src/ir/expressions/BinaryBooleanFunctionExpression.h deleted file mode 100644 index b0cec5906..000000000 --- a/src/ir/expressions/BinaryBooleanFunctionExpression.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * BinaryBooleanFunctionExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ - -#include "BinaryExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a binary function expression of boolean type. - */ - class BinaryBooleanFunctionExpression : public BinaryExpression { - public: - /*! - * An enum type specifying the different functions applicable. - */ - enum FunctionType {AND, OR}; - - /*! - * Creates a binary boolean function expression tree node with the given children and function type. - * - * @param left The left child of the node. - * @param right The right child of the node. - * @param functionType The operator that is to be applied to the two children. - */ - BinaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType); - - /*! - * Copy-constructs from the given expression. - * - * @param binaryBooleanFunctionExpression The expression to copy. - */ - BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression const& binaryBooleanFunctionExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - /*! - * Retrieves the operator that is associated with this node. - * - * @param The operator that is associated with this node. - */ - FunctionType getFunctionType() const; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The operator that is associated with this node. - FunctionType functionType; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ */ diff --git a/src/ir/expressions/BinaryExpression.cpp b/src/ir/expressions/BinaryExpression.cpp deleted file mode 100644 index 417cc9301..000000000 --- a/src/ir/expressions/BinaryExpression.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * BinaryBooleanFunctionExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include "BinaryExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - BinaryExpression::BinaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right) - : BaseExpression(type), left(std::move(left)), right(std::move(right)) { - // Nothing to do here. - } - - BinaryExpression::BinaryExpression(BinaryExpression const& binaryExpression) : BaseExpression(binaryExpression.getType()), left(binaryExpression.left->clone()), right(binaryExpression.right->clone()) { - // Nothing to do here. - } - - BaseExpression* BinaryExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) { - // Get the new left successor recursively. - BaseExpression* newLeftSuccessor = left->performSubstitution(substitution); - - // If the left successor changed, we need to update it. If it did not change, this must not be executed, - // because assigning to the unique_ptr will destroy the current successor immediately. - if (newLeftSuccessor != left.get()) { - left = std::unique_ptr<BaseExpression>(newLeftSuccessor); - } - - // Now do the same thing for the right successor. - BaseExpression* newRightSuccessor = right->performSubstitution(substitution); - if (newRightSuccessor != right.get()) { - right = std::unique_ptr<BaseExpression>(newRightSuccessor); - } - - return this; - } - - std::unique_ptr<BaseExpression> const& BinaryExpression::getLeft() const { - return left; - } - - std::unique_ptr<BaseExpression> const& BinaryExpression::getRight() const { - return right; - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/BinaryExpression.h b/src/ir/expressions/BinaryExpression.h deleted file mode 100644 index 1d6560863..000000000 --- a/src/ir/expressions/BinaryExpression.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * BinaryExpression.h - * - * Created on: 27.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_BINARYEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_BINARYEXPRESSION_H_ - -#include "src/ir/expressions/BaseExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a generic binary expression. - */ - class BinaryExpression : public BaseExpression { - public: - /*! - * Constructs a binary expression with the given type and children. - * @param type The type of the binary expression. - * @param left The left child of the binary expression. - * @param right The right child of the binary expression. - */ - BinaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right); - - /*! - * Copy-constructs from the given expression. - * - * @param binaryExpression The expression to copy. - */ - BinaryExpression(BinaryExpression const& binaryExpression); - - /*! - * Retrieves the left child of the expression node. - * - * @return The left child of the expression node. - */ - std::unique_ptr<BaseExpression> const& getLeft() const; - - /*! - * Retrieves the right child of the expression node. - * - * @return The right child of the expression node. - */ - std::unique_ptr<BaseExpression> const& getRight() const; - - protected: - virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) override; - - private: - // The left child of the binary expression. - std::unique_ptr<BaseExpression> left; - - // The right child of the binary expression. - std::unique_ptr<BaseExpression> right; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_BINARYEXPRESSION_H_ */ diff --git a/src/ir/expressions/BinaryNumericalFunctionExpression.cpp b/src/ir/expressions/BinaryNumericalFunctionExpression.cpp deleted file mode 100644 index a80e04ae4..000000000 --- a/src/ir/expressions/BinaryNumericalFunctionExpression.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * BinaryBooleanFunctionExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include <sstream> -#include <algorithm> - -#include "BinaryNumericalFunctionExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - BinaryNumericalFunctionExpression::BinaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType) - : BinaryExpression(type, std::move(left), std::move(right)), functionType(functionType) { - // Nothing to do here. - } - - BinaryNumericalFunctionExpression::BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression const& binaryNumericalFunctionExpression) - : BinaryExpression(binaryNumericalFunctionExpression), functionType(binaryNumericalFunctionExpression.functionType) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> BinaryNumericalFunctionExpression::clone() const { - return std::unique_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getType(), this->getLeft()->clone(), this->getRight()->clone(), functionType)); - } - - std::unique_ptr<BaseExpression> BinaryNumericalFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getType(), this->getLeft()->clone(renaming, variableState), this->getRight()->clone(renaming, variableState), this->functionType)); - } - - BinaryNumericalFunctionExpression::FunctionType BinaryNumericalFunctionExpression::getFunctionType() const { - return functionType; - } - - int_fast64_t BinaryNumericalFunctionExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (this->getType() != int_) { - BaseExpression::getValueAsInt(variableValues); - } - - int_fast64_t resultLeft = this->getLeft()->getValueAsInt(variableValues); - int_fast64_t resultRight = this->getRight()->getValueAsInt(variableValues); - switch(functionType) { - case PLUS: return resultLeft + resultRight; break; - case MINUS: return resultLeft - resultRight; break; - case TIMES: return resultLeft * resultRight; break; - case DIVIDE: return resultLeft / resultRight; break; - case MIN: return std::min(resultLeft, resultRight); break; - case MAX: return std::max(resultLeft, resultRight); break; - default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Unknown numeric binary operator: '" << functionType << "'."; - } - } - - double BinaryNumericalFunctionExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (this->getType() != double_ && this->getType() != int_) { - BaseExpression::getValueAsDouble(variableValues); - } - - double resultLeft = this->getLeft()->getValueAsDouble(variableValues); - double resultRight = this->getRight()->getValueAsDouble(variableValues); - switch(functionType) { - case PLUS: return resultLeft + resultRight; break; - case MINUS: return resultLeft - resultRight; break; - case TIMES: return resultLeft * resultRight; break; - case DIVIDE: return resultLeft / resultRight; break; - case MIN: return std::min(resultLeft, resultRight); break; - case MAX: return std::max(resultLeft, resultRight); break; - default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Unknown numeric binary operator: '" << functionType << "'."; - } - } - - void BinaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string BinaryNumericalFunctionExpression::toString() const { - std::stringstream result; - switch (functionType) { - case PLUS: result << "(" << this->getLeft()->toString() << " + " << this->getRight()->toString() << ")"; break; - case MINUS: result << "(" << this->getLeft()->toString() << " - " << this->getRight()->toString() << ")"; break; - case TIMES: result << "(" << this->getLeft()->toString() << " * " << this->getRight()->toString() << ")"; break; - case DIVIDE: result << "(" << this->getLeft()->toString() << " / " << this->getRight()->toString() << ")"; break; - case MIN: result << "min(" << this->getLeft()->toString() << ", " << this->getRight()->toString() << ")"; break; - case MAX: result << "max(" << this->getLeft()->toString() << ", " << this->getRight()->toString() << ")"; break; - } - return result.str(); - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/BinaryNumericalFunctionExpression.h b/src/ir/expressions/BinaryNumericalFunctionExpression.h deleted file mode 100644 index 846ceb99a..000000000 --- a/src/ir/expressions/BinaryNumericalFunctionExpression.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * BinaryFunctionExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_BINARYFUNCTIONEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_BINARYFUNCTIONEXPRESSION_H_ - -#include "src/ir/expressions/BinaryExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a binary function expression of numerical type. - */ - class BinaryNumericalFunctionExpression : public BinaryExpression { - public: - /*! - * An enum type specifying the different functions applicable. - */ - enum FunctionType {PLUS, MINUS, TIMES, DIVIDE, MIN, MAX}; - - /*! - * Creates a binary numerical function expression with the given type, children and function type. - * - * @param type The type of the expression tree node. - * @param left The left child of the expression tree node. - * @param right The right child of the expression tree node. - * @param functionType The function that is applied to the children of this node. - */ - BinaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType); - - /*! - * Performs a deep-copy of the given expression. - * - * @param binaryNumericalFunctionExpression The expression to copy. - */ - BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression const& binaryNumericalFunctionExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - /*! - * Retrieves the operator that is associated with this node. - * - * @param The operator that is associated with this node. - */ - FunctionType getFunctionType() const; - - virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The operator that is associated with this node. - FunctionType functionType; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_BINARYFUNCTIONEXPRESSION_H_ */ diff --git a/src/ir/expressions/BinaryRelationExpression.cpp b/src/ir/expressions/BinaryRelationExpression.cpp deleted file mode 100644 index 5c08e7f33..000000000 --- a/src/ir/expressions/BinaryRelationExpression.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * BinaryBooleanFunctionExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "BinaryRelationExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - BinaryRelationExpression::BinaryRelationExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, RelationType relationType) - : BinaryExpression(bool_, std::move(left), std::move(right)), relationType(relationType) { - // Nothing to do here. - } - - BinaryRelationExpression::BinaryRelationExpression(BinaryRelationExpression const& binaryRelationExpression) - : BinaryExpression(binaryRelationExpression), relationType(binaryRelationExpression.relationType) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> BinaryRelationExpression::clone() const { - return std::unique_ptr<BaseExpression>(new BinaryRelationExpression(this->getLeft()->clone(), this->getRight()->clone(), relationType)); - } - - std::unique_ptr<BaseExpression> BinaryRelationExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new BinaryRelationExpression(this->getLeft()->clone(renaming, variableState), this->getRight()->clone(renaming, variableState), this->relationType)); - } - - bool BinaryRelationExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - int_fast64_t resultLeft = this->getLeft()->getValueAsInt(variableValues); - int_fast64_t resultRight = this->getRight()->getValueAsInt(variableValues); - switch(relationType) { - case EQUAL: return resultLeft == resultRight; break; - case NOT_EQUAL: return resultLeft != resultRight; break; - case LESS: return resultLeft < resultRight; break; - case LESS_OR_EQUAL: return resultLeft <= resultRight; break; - case GREATER: return resultLeft > resultRight; break; - case GREATER_OR_EQUAL: return resultLeft >= resultRight; break; - default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Unknown boolean binary relation: '" << relationType << "'."; - } - } - - BinaryRelationExpression::RelationType BinaryRelationExpression::getRelationType() const { - return relationType; - } - - void BinaryRelationExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string BinaryRelationExpression::toString() const { - std::stringstream result; - result << "(" << this->getLeft()->toString(); - switch (relationType) { - case EQUAL: result << " = "; break; - case NOT_EQUAL: result << " != "; break; - case LESS: result << " < "; break; - case LESS_OR_EQUAL: result << " <= "; break; - case GREATER: result << " > "; break; - case GREATER_OR_EQUAL: result << " >= "; break; - } - result << this->getRight()->toString() << ")"; - - return result.str(); - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/BinaryRelationExpression.h b/src/ir/expressions/BinaryRelationExpression.h deleted file mode 100644 index 873cbe5bf..000000000 --- a/src/ir/expressions/BinaryRelationExpression.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * BinaryRelationExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ - -#include "src/ir/expressions/BinaryExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a binary relation expression of boolean type. - */ - class BinaryRelationExpression : public BinaryExpression { - public: - /*! - * An enum type specifying the different relations applicable. - */ - enum RelationType {EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, GREATER_OR_EQUAL}; - - /*! - * Creates a binary relation expression tree node with the given children and relation type. - * - * @param left The left child of the binary expression. - * @param right The right child of the binary expression. - * @param relationType The type of the relation associated with this node. - */ - BinaryRelationExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, RelationType relationType); - - /*! - * Copy-constructs from the given expression. - * - * @param binaryRelationExpression The expression to copy. - */ - BinaryRelationExpression(BinaryRelationExpression const& binaryRelationExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - /*! - * Retrieves the relation that is associated with this node. - * - * @param The relation that is associated with this node. - */ - RelationType getRelationType() const; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The relation operator associated with this node. - RelationType relationType; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ */ diff --git a/src/ir/expressions/BooleanConstantExpression.cpp b/src/ir/expressions/BooleanConstantExpression.cpp deleted file mode 100644 index 2022e8796..000000000 --- a/src/ir/expressions/BooleanConstantExpression.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * BooleanConstantExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include "BooleanConstantExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - BooleanConstantExpression::BooleanConstantExpression(std::string const& constantName) : ConstantExpression<bool>(bool_, constantName) { - // Nothing to do here. - } - - BooleanConstantExpression::BooleanConstantExpression(BooleanConstantExpression const& booleanConstantExpression) : ConstantExpression(booleanConstantExpression) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> BooleanConstantExpression::clone() const { - return std::unique_ptr<BaseExpression>(new BooleanConstantExpression(*this)); - } - - std::unique_ptr<BaseExpression> BooleanConstantExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new BooleanConstantExpression(*this)); - } - - bool BooleanConstantExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (!this->isDefined()) { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Boolean constant '" << this->getConstantName() << "' is undefined."; - } else { - return this->getValue(); - } - } - - void BooleanConstantExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/BooleanConstantExpression.h b/src/ir/expressions/BooleanConstantExpression.h deleted file mode 100644 index 4838ba595..000000000 --- a/src/ir/expressions/BooleanConstantExpression.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * BooleanConstantExpression.h - * - * Created on: 04.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ - -#include "ConstantExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a boolean constant expression. - */ - class BooleanConstantExpression : public ConstantExpression<bool> { - public: - /*! - * Creates a boolean constant expression with the given constant name. - * - * @param constantName The name of the constant to use. - */ - BooleanConstantExpression(std::string const& constantName); - - /*! - * Copy-constructs from the given expression. - * - * @param booleanConstantExpression The expression to copy. - */ - BooleanConstantExpression(BooleanConstantExpression const& booleanConstantExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ */ diff --git a/src/ir/expressions/BooleanLiteralExpression.cpp b/src/ir/expressions/BooleanLiteralExpression.cpp deleted file mode 100644 index 89e6b7876..000000000 --- a/src/ir/expressions/BooleanLiteralExpression.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * BooleanLiteralExpression.cpp - * - * Created on: 04.01.2013 - * Author: Christian Dehnert - */ - -#include "BooleanLiteralExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - BooleanLiteralExpression::BooleanLiteralExpression(bool value) : BaseExpression(bool_), value(value) { - // Nothing to do here. - } - - BooleanLiteralExpression::BooleanLiteralExpression(BooleanLiteralExpression const& booleanLiteralExpression) - : BaseExpression(booleanLiteralExpression), value(booleanLiteralExpression.value) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> BooleanLiteralExpression::clone() const { - return std::unique_ptr<BaseExpression>(new BooleanLiteralExpression(*this)); - } - - std::unique_ptr<BaseExpression> BooleanLiteralExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new BooleanLiteralExpression(this->value)); - } - - bool BooleanLiteralExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - return value; - } - - void BooleanLiteralExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string BooleanLiteralExpression::toString() const { - if (value) { - return std::string("true"); - } else { - return std::string("false"); - } - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/BooleanLiteralExpression.h b/src/ir/expressions/BooleanLiteralExpression.h deleted file mode 100644 index 1fb747a78..000000000 --- a/src/ir/expressions/BooleanLiteralExpression.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * BooleanLiteralExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ - -#include "src/ir/expressions/BaseExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a boolean literal. - */ - class BooleanLiteralExpression : public BaseExpression { - public: - /*! - * Creates a boolean literal expression with the given value. - * - * @param value The value for the boolean literal. - */ - BooleanLiteralExpression(bool value); - - /*! - * Copy-constructs from the given expression. - * - * @param booleanLiteralExpression The expression to copy. - */ - BooleanLiteralExpression(BooleanLiteralExpression const& booleanLiteralExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The value of the boolean literal. - bool value; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ */ diff --git a/src/ir/expressions/ConstantExpression.h b/src/ir/expressions/ConstantExpression.h deleted file mode 100644 index dc1763c33..000000000 --- a/src/ir/expressions/ConstantExpression.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * ConstantExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_CONSTANTEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_CONSTANTEXPRESSION_H_ - -#include "BaseExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - // A struct for storing whether the constant was defined and if so, what value it holds. - template<class T> - struct ConstantDefinitionStruct { - /*! - * Constructs a structure indicating that the constant has been defined with the given value. - * - * @param value The value with which the constant was defined. - */ - ConstantDefinitionStruct(T value) : value(value), defined(true) { - // Nothing to do here. - } - - /*! - * Constructs a structure indicating that the constant has not yet been defined. - * - * @param value The value with which the constant was defined. - */ - ConstantDefinitionStruct() : value(), defined(false) { - // Nothing to do here. - } - - T value; - bool defined; - }; - - /*! - * A class representing a generic constant expression. - */ - template<class T> - class ConstantExpression : public BaseExpression { - public: - /*! - * Constructs a constant expression of the given type with the given constant name. - * - * @param type The type of the constant. - * @param constantName The name of the constant. - */ - ConstantExpression(ReturnType type, std::string const& constantName) : BaseExpression(type), constantName(constantName), valueStructPointer(new ConstantDefinitionStruct<T>()) { - // Nothing to do here. - } - - /*! - * Copy-constructs from the given expression. - * - * @param constantExpression The expression to copy. - */ - ConstantExpression(ConstantExpression const& constantExpression) : BaseExpression(constantExpression), constantName(constantExpression.constantName), valueStructPointer(constantExpression.valueStructPointer) { - // Nothing to do here. - } - - /*! - * Retrieves the name of the constant. - * - * @return The name of the constant. - */ - std::string const& getConstantName() const { - return constantName; - } - - virtual std::string toString() const override { - std::stringstream result; - if (this->valueStructPointer->defined) { - result << this->valueStructPointer->value; - } else { - result << this->getConstantName(); - } - return result.str(); - } - - /*! - * Retrieves whether the constant is defined or not. - * - * @return True if the constant is defined. - */ - bool isDefined() const { - return this->valueStructPointer->defined; - } - - /*! - * Retrieves the value of the constant if it is defined. - */ - T getValue() const { - return this->valueStructPointer->value; - } - - /*! - * Defines the constant using the given value. - * - * @param value The value to use for defining the constant. - */ - void define(T value) { - this->valueStructPointer->defined = true; - this->valueStructPointer->value = value; - } - - /*! - * Undefines the value that was previously set for this constant (if any). - */ - void undefine() { - this->valueStructPointer->defined = false; - this->valueStructPointer->value = T(); - } - - private: - // The name of the constant. - std::string constantName; - - // The definedness status and (if applicable) the value of the constant. - std::shared_ptr<ConstantDefinitionStruct<T>> valueStructPointer; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_CONSTANTEXPRESSION_H_ */ diff --git a/src/ir/expressions/DoubleConstantExpression.cpp b/src/ir/expressions/DoubleConstantExpression.cpp deleted file mode 100644 index bc29cbf26..000000000 --- a/src/ir/expressions/DoubleConstantExpression.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * DoubleConstantExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include "DoubleConstantExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - DoubleConstantExpression::DoubleConstantExpression(std::string const& constantName) : ConstantExpression<double>(double_, constantName) { - // Nothing to do here. - } - - DoubleConstantExpression::DoubleConstantExpression(DoubleConstantExpression const& doubleConstantExpression) : ConstantExpression(doubleConstantExpression) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> DoubleConstantExpression::clone() const { - return std::unique_ptr<BaseExpression>(new DoubleConstantExpression(*this)); - } - - std::unique_ptr<BaseExpression> DoubleConstantExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new DoubleConstantExpression(*this)); - } - - double DoubleConstantExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (!this->isDefined()) { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Double constant '" << this->getConstantName() << "' is undefined."; - } else { - return this->getValue(); - } - } - - void DoubleConstantExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/DoubleConstantExpression.h b/src/ir/expressions/DoubleConstantExpression.h deleted file mode 100644 index 9eaa6eb18..000000000 --- a/src/ir/expressions/DoubleConstantExpression.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * DoubleConstantExpression.h - * - * Created on: 04.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ - -#include "ConstantExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a constant expression of type double. - */ - class DoubleConstantExpression : public ConstantExpression<double> { - public: - /*! - * Creates a double constant expression with the given constant name. - * - * @param constantName The name of the constant to use. - */ - DoubleConstantExpression(std::string const& constantName); - - /*! - * Copy-constructs from the given expression. - * - * @param doubleConstantExpression The expression to copy. - */ - DoubleConstantExpression(DoubleConstantExpression const& doubleConstantExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ */ diff --git a/src/ir/expressions/DoubleLiteralExpression.cpp b/src/ir/expressions/DoubleLiteralExpression.cpp deleted file mode 100644 index 08663f8f7..000000000 --- a/src/ir/expressions/DoubleLiteralExpression.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * DoubleLiteralExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "DoubleLiteralExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - DoubleLiteralExpression::DoubleLiteralExpression(double value) : BaseExpression(double_), value(value) { - // Nothing to do here. - } - - DoubleLiteralExpression::DoubleLiteralExpression(DoubleLiteralExpression const& doubleLiteralExpression) - : BaseExpression(doubleLiteralExpression), value(doubleLiteralExpression.value) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> DoubleLiteralExpression::clone() const { - return std::unique_ptr<BaseExpression>(new DoubleLiteralExpression(*this)); - } - - std::unique_ptr<BaseExpression> DoubleLiteralExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new DoubleLiteralExpression(this->value)); - } - - double DoubleLiteralExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - return value; - } - - void DoubleLiteralExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string DoubleLiteralExpression::toString() const { - std::stringstream result; - result << value; - return result.str(); - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/DoubleLiteralExpression.h b/src/ir/expressions/DoubleLiteralExpression.h deleted file mode 100644 index 7105858c2..000000000 --- a/src/ir/expressions/DoubleLiteralExpression.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * DoubleLiteralExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_ - -#include "src/ir/expressions/BaseExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a double literal. - */ - class DoubleLiteralExpression : public BaseExpression { - public: - /*! - * Creates a double literal expression with the given value. - * - * @param value The value for the double literal. - */ - DoubleLiteralExpression(double value); - - /*! - * Copy-constructs from the given expression. - * - * @param doubleLiteralExpression The expression to copy. - */ - DoubleLiteralExpression(DoubleLiteralExpression const& doubleLiteralExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The value of the double literal. - double value; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_ */ diff --git a/src/ir/expressions/ExpressionVisitor.h b/src/ir/expressions/ExpressionVisitor.h deleted file mode 100644 index d301e9792..000000000 --- a/src/ir/expressions/ExpressionVisitor.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ExpressionVisitor.h - * - * Created on: 26.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_EXPRESSIONVISITOR_H_ -#define STORM_IR_EXPRESSIONS_EXPRESSIONVISITOR_H_ - -namespace storm { - namespace ir { - namespace expressions { - - class BaseExpression; - class BinaryBooleanFunctionExpression; - class BinaryNumericalFunctionExpression; - class BinaryRelationExpression; - class BooleanConstantExpression; - class BooleanLiteralExpression; - class DoubleConstantExpression; - class DoubleLiteralExpression; - class IntegerConstantExpression; - class IntegerLiteralExpression; - class UnaryBooleanFunctionExpression; - class UnaryNumericalFunctionExpression; - class VariableExpression; - - class ExpressionVisitor { - public: - virtual void visit(BinaryBooleanFunctionExpression* expression) = 0; - virtual void visit(BinaryNumericalFunctionExpression* expression) = 0; - virtual void visit(BinaryRelationExpression* expression) = 0; - virtual void visit(BooleanConstantExpression* expression) = 0; - virtual void visit(BooleanLiteralExpression* expression) = 0; - virtual void visit(DoubleConstantExpression* expression) = 0; - virtual void visit(DoubleLiteralExpression* expression) = 0; - virtual void visit(IntegerConstantExpression* expression) = 0; - virtual void visit(IntegerLiteralExpression* expression) = 0; - virtual void visit(UnaryBooleanFunctionExpression* expression) = 0; - virtual void visit(UnaryNumericalFunctionExpression* expression) = 0; - virtual void visit(VariableExpression* expression) = 0; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_EXPRESSIONVISITOR_H_ */ diff --git a/src/ir/expressions/Expressions.h b/src/ir/expressions/Expressions.h deleted file mode 100644 index 634a0585d..000000000 --- a/src/ir/expressions/Expressions.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Expressions.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_EXPRESSIONS_H_ -#define STORM_IR_EXPRESSIONS_EXPRESSIONS_H_ - -#include "BaseExpression.h" -#include "BinaryBooleanFunctionExpression.h" -#include "BinaryNumericalFunctionExpression.h" -#include "BinaryRelationExpression.h" -#include "BooleanLiteralExpression.h" -#include "DoubleLiteralExpression.h" -#include "IntegerLiteralExpression.h" -#include "UnaryBooleanFunctionExpression.h" -#include "UnaryNumericalFunctionExpression.h" -#include "VariableExpression.h" -#include "ConstantExpression.h" -#include "BooleanConstantExpression.h" -#include "IntegerConstantExpression.h" -#include "DoubleConstantExpression.h" - -#endif /* STORM_IR_EXPRESSIONS_EXPRESSIONS_H_ */ diff --git a/src/ir/expressions/IntegerConstantExpression.cpp b/src/ir/expressions/IntegerConstantExpression.cpp deleted file mode 100644 index bcc5cb0eb..000000000 --- a/src/ir/expressions/IntegerConstantExpression.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * IntegerConstantExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include "IntegerConstantExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - IntegerConstantExpression::IntegerConstantExpression(std::string const& constantName) : ConstantExpression(int_, constantName) { - // Nothing to do here. - } - - IntegerConstantExpression::IntegerConstantExpression(IntegerConstantExpression const& integerConstantExpression) : ConstantExpression(integerConstantExpression) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> IntegerConstantExpression::clone() const { - return std::unique_ptr<BaseExpression>(new IntegerConstantExpression(*this)); - } - - std::unique_ptr<BaseExpression> IntegerConstantExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new IntegerConstantExpression(*this)); - } - - double IntegerConstantExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - return static_cast<double>(getValueAsInt(variableValues)); - } - - int_fast64_t IntegerConstantExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (!this->isDefined()) { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Integer constant '" << this->getConstantName() << "' is undefined."; - } else { - return this->getValue(); - } - } - - void IntegerConstantExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/IntegerConstantExpression.h b/src/ir/expressions/IntegerConstantExpression.h deleted file mode 100644 index 04370574d..000000000 --- a/src/ir/expressions/IntegerConstantExpression.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * IntegerConstantExpression.h - * - * Created on: 04.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ - -#include "ConstantExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a constant expression of type integer. - */ - class IntegerConstantExpression : public ConstantExpression<int_fast64_t> { - public: - /*! - * Creates an integer constant expression with the given constant name. - * - * @param constantName The name of the constant to use. - */ - IntegerConstantExpression(std::string const& constantName); - - /*! - * Copy-constructs from the given expression. - * - * @param integerConstantExpression The expression to copy. - */ - IntegerConstantExpression(IntegerConstantExpression const& integerConstantExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ */ diff --git a/src/ir/expressions/IntegerLiteralExpression.cpp b/src/ir/expressions/IntegerLiteralExpression.cpp deleted file mode 100644 index ed3277f18..000000000 --- a/src/ir/expressions/IntegerLiteralExpression.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * IntegerLiteralExpression.cpp - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "IntegerLiteralExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - IntegerLiteralExpression::IntegerLiteralExpression(int_fast64_t value) : BaseExpression(int_), value(value) { - // Nothing to do here. - } - - IntegerLiteralExpression::IntegerLiteralExpression(IntegerLiteralExpression const& integerLiteralExpression) - : BaseExpression(integerLiteralExpression), value(integerLiteralExpression.value) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> IntegerLiteralExpression::clone() const { - return std::unique_ptr<BaseExpression>(new IntegerLiteralExpression(*this)); - } - - std::unique_ptr<BaseExpression> IntegerLiteralExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new IntegerLiteralExpression(this->value)); - } - - double IntegerLiteralExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - return static_cast<double>(value); - } - - int_fast64_t IntegerLiteralExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - return value; - } - - void IntegerLiteralExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string IntegerLiteralExpression::toString() const { - std::stringstream result; - result << value; - return result.str(); - } - - } // namespace expressions - } // namespace ir -} // namespace storm \ No newline at end of file diff --git a/src/ir/expressions/IntegerLiteralExpression.h b/src/ir/expressions/IntegerLiteralExpression.h deleted file mode 100644 index cb1041684..000000000 --- a/src/ir/expressions/IntegerLiteralExpression.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * IntegerLiteralExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ - -#include "src/ir/expressions/BaseExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing an integer literal. - */ - class IntegerLiteralExpression : public BaseExpression { - public: - /*! - * Creates an integer literal expression with the given value. - * - * @param value The value for the integer literal. - */ - IntegerLiteralExpression(int_fast64_t value); - - /*! - * Copy-constructs from the given expression. - * - * @param integerLiteralExpression The expression to copy. - */ - IntegerLiteralExpression(IntegerLiteralExpression const& integerLiteralExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The value of the double literal. - int_fast64_t value; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ */ diff --git a/src/ir/expressions/UnaryBooleanFunctionExpression.cpp b/src/ir/expressions/UnaryBooleanFunctionExpression.cpp deleted file mode 100644 index 3b0e6ca03..000000000 --- a/src/ir/expressions/UnaryBooleanFunctionExpression.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * UnaryBooleanFunctionExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include <sstream> - -#include "UnaryBooleanFunctionExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - UnaryBooleanFunctionExpression::UnaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& child, FunctionType functionType) : UnaryExpression(bool_, std::move(child)), functionType(functionType) { - // Nothing to do here. - } - - UnaryBooleanFunctionExpression::UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression const& unaryBooleanFunctionExpression) : UnaryExpression(unaryBooleanFunctionExpression), functionType(unaryBooleanFunctionExpression.functionType) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> UnaryBooleanFunctionExpression::clone() const { - return std::unique_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(this->getChild()->clone(), functionType)); - } - - std::unique_ptr<BaseExpression> UnaryBooleanFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(this->getChild()->clone(renaming, variableState), this->functionType)); - } - - UnaryBooleanFunctionExpression::FunctionType UnaryBooleanFunctionExpression::getFunctionType() const { - return functionType; - } - - bool UnaryBooleanFunctionExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - bool resultChild = this->getChild()->getValueAsBool(variableValues); - switch(functionType) { - case NOT: return !resultChild; break; - default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Unknown boolean unary operator: '" << functionType << "'."; - } - } - - void UnaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string UnaryBooleanFunctionExpression::toString() const { - std::stringstream result; - result << "("; - switch (functionType) { - case NOT: result << "!"; break; - } - result << this->getChild()->toString() << ")"; - - return result.str(); - } - - } // namespace expressions - } // namespace ir -} // namespace storm diff --git a/src/ir/expressions/UnaryBooleanFunctionExpression.h b/src/ir/expressions/UnaryBooleanFunctionExpression.h deleted file mode 100644 index a3087f5e5..000000000 --- a/src/ir/expressions/UnaryBooleanFunctionExpression.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * UnaryBooleanFunctionExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ - -#include "UnaryExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a unary function expression of boolean type. - */ - class UnaryBooleanFunctionExpression : public UnaryExpression { - public: - /*! - * An enum type specifying the different functions applicable. - */ - enum FunctionType {NOT}; - - /*! - * Creates a unary boolean function expression tree node with the given child and function type. - * - * @param child The child of the node. - * @param functionType The operator that is to be applied to the two children. - */ - UnaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& child, FunctionType functionType); - - /*! - * Copy-constructs from the given expression. - * - * @param unaryBooleanFunctionExpression The expression to copy. - */ - UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression const& unaryBooleanFunctionExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - /*! - * Retrieves the operator that is associated with this node. - * - * @param The operator that is associated with this node. - */ - FunctionType getFunctionType() const; - - virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The operator that is associated with this node. - FunctionType functionType; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ */ diff --git a/src/ir/expressions/UnaryExpression.cpp b/src/ir/expressions/UnaryExpression.cpp deleted file mode 100644 index 31463aff3..000000000 --- a/src/ir/expressions/UnaryExpression.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * UnaryExpression.cpp - * - * Created on: 27.01.2013 - * Author: Christian Dehnert - */ - -#include "UnaryExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - UnaryExpression::UnaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child) : BaseExpression(type), child(std::move(child)) { - // Nothing to do here. - } - - UnaryExpression::UnaryExpression(UnaryExpression const& unaryExpression) : BaseExpression(unaryExpression), child(unaryExpression.child->clone()) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> const& UnaryExpression::getChild() const { - return child; - } - - BaseExpression* UnaryExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) { - BaseExpression* newChild = child->performSubstitution(substitution); - - // Only update the child if it changed, because otherwise the child gets destroyed. - if (newChild != child.get()) { - child = std::unique_ptr<BaseExpression>(newChild); - } - - return this; - } - - } // namespace expressions - } // namespace ir -} // namespace storm diff --git a/src/ir/expressions/UnaryExpression.h b/src/ir/expressions/UnaryExpression.h deleted file mode 100644 index cfc685455..000000000 --- a/src/ir/expressions/UnaryExpression.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * UnaryExpression.h - * - * Created on: 27.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_UNARYEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_UNARYEXPRESSION_H_ - -#include "BaseExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a generic unary expression. - */ - class UnaryExpression : public BaseExpression { - public: - /*! - * Constructs a unary expression with the given type and child. - * @param type The type of the unary expression. - * @param right The child of the unary expression. - */ - UnaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child); - - /*! - * Copy-constructs from the given expression. - * - * @param unaryExpression The expression to copy. - */ - UnaryExpression(UnaryExpression const& unaryExpression); - - /*! - * Retrieves the child of the expression node. - * - * @return The child of the expression node. - */ - std::unique_ptr<BaseExpression> const& getChild() const; - - protected: - virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) override; - - private: - // The left child of the unary expression. - std::unique_ptr<BaseExpression> child; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_UNARYEXPRESSION_H_ */ diff --git a/src/ir/expressions/UnaryNumericalFunctionExpression.cpp b/src/ir/expressions/UnaryNumericalFunctionExpression.cpp deleted file mode 100644 index 6b4b1fbb2..000000000 --- a/src/ir/expressions/UnaryNumericalFunctionExpression.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * UnaryFunctionExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#include <cmath> - -#include "UnaryNumericalFunctionExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - UnaryNumericalFunctionExpression::UnaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child, FunctionType functionType) : UnaryExpression(type, std::move(child)), functionType(functionType) { - // Nothing to do here. - } - - UnaryNumericalFunctionExpression::UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression const& unaryNumericalFunctionExpression) : UnaryExpression(unaryNumericalFunctionExpression), functionType(unaryNumericalFunctionExpression.functionType) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> UnaryNumericalFunctionExpression::clone() const { - return std::unique_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getType(), this->getChild()->clone(), functionType)); - } - - std::unique_ptr<BaseExpression> UnaryNumericalFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - return std::unique_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getType(), this->getChild()->clone(renaming, variableState), this->functionType)); - } - - int_fast64_t UnaryNumericalFunctionExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (this->getType() != int_) { - BaseExpression::getValueAsInt(variableValues); - } - - int_fast64_t resultChild = this->getChild()->getValueAsInt(variableValues); - switch(functionType) { - case MINUS: return -resultChild; break; - case FLOOR: return static_cast<int_fast64_t>(std::floor(resultChild)); break; - case CEIL: return static_cast<int_fast64_t>(std::ceil(resultChild)); break; - default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Unknown numerical unary operator: '" << functionType << "'."; - } - } - - double UnaryNumericalFunctionExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (this->getType() != double_ && this->getType() != int_) { - BaseExpression::getValueAsDouble(variableValues); - } - - double resultChild = this->getChild()->getValueAsDouble(variableValues); - switch(functionType) { - case MINUS: return -resultChild; break; - case FLOOR: return std::floor(resultChild); break; - case CEIL: return std::ceil(resultChild); break; - default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " - << "Unknown numerical unary operator: '" << functionType << "'."; - } - } - - UnaryNumericalFunctionExpression::FunctionType UnaryNumericalFunctionExpression::getFunctionType() const { - return functionType; - } - - void UnaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string UnaryNumericalFunctionExpression::toString() const { - std::stringstream result; - result << "("; - switch (functionType) { - case MINUS: result << "-"; break; - case FLOOR: result << "floor("; break; - case CEIL: result << "ceil("; break; - } - result << this->getChild()->toString() << ")"; - - return result.str(); - } - - } // namespace expressions - } // namespace ir -} // namespace storm - diff --git a/src/ir/expressions/UnaryNumericalFunctionExpression.h b/src/ir/expressions/UnaryNumericalFunctionExpression.h deleted file mode 100644 index bcb942378..000000000 --- a/src/ir/expressions/UnaryNumericalFunctionExpression.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * UnaryFunctionExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_UNARYFUNCTIONEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_UNARYFUNCTIONEXPRESSION_H_ - -#include "UnaryExpression.h" - -namespace storm { - namespace ir { - namespace expressions { - - /*! - * A class representing a unary function expression of numerical type. - */ - class UnaryNumericalFunctionExpression : public UnaryExpression { - public: - /*! - * An enum type specifying the different functions applicable. - */ - enum FunctionType {MINUS, FLOOR, CEIL}; - - /*! - * Creates a unary numerical function expression tree node with the given child and function type. - * - * @param child The child of the node. - * @param functionType The operator that is to be applied to the two children. - */ - UnaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child, FunctionType functionType); - - /*! - * Copy-constructs from the given expression. - * - * @param unaryNumericalFunctionExpression The expression to copy. - */ - UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression const& unaryNumericalFunctionExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - /*! - * Retrieves the operator that is associated with this node. - * - * @param The operator that is associated with this node. - */ - FunctionType getFunctionType() const; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - private: - // The operator that is associated with this node. - FunctionType functionType; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_UNARYFUNCTIONEXPRESSION_H_ */ diff --git a/src/ir/expressions/VariableExpression.cpp b/src/ir/expressions/VariableExpression.cpp deleted file mode 100644 index 9bf09a734..000000000 --- a/src/ir/expressions/VariableExpression.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * VariableExpression.cpp - * - * Created on: 10.06.2013 - * Author: Christian Dehnert - */ - -#include "VariableExpression.h" -#include "src/parser/prismparser/VariableState.h" -#include "src/exceptions/ExpressionEvaluationException.h" - -namespace storm { - namespace ir { - namespace expressions { - - VariableExpression::VariableExpression(ReturnType type, std::string const& variableName) : BaseExpression(type), globalIndex(0), variableName(variableName) { - // Nothing to do here. - } - - VariableExpression::VariableExpression(ReturnType type, uint_fast64_t globalIndex, std::string const& variableName) - : BaseExpression(type), globalIndex(globalIndex), variableName(variableName) { - // Nothing to do here. - } - - VariableExpression::VariableExpression(VariableExpression const& variableExpression) : BaseExpression(variableExpression), globalIndex(variableExpression.globalIndex), variableName(variableExpression.variableName) { - // Nothing to do here. - } - - std::unique_ptr<BaseExpression> VariableExpression::clone() const { - return std::unique_ptr<BaseExpression>(new VariableExpression(*this)); - } - - std::unique_ptr<BaseExpression> VariableExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const { - // Perform the proper cloning. - auto renamingPair = renaming.find(this->variableName); - if (renamingPair != renaming.end()) { - if (this->getType() == int_) { - return variableState.getIntegerVariableExpression(renamingPair->second)->clone(); - } else { - return variableState.getBooleanVariableExpression(renamingPair->second)->clone(); - } - } else { - if (this->getType() == int_) { - return variableState.getIntegerVariableExpression(this->variableName)->clone(); - } else { - return variableState.getBooleanVariableExpression(this->variableName)->clone(); - } - } - } - - BaseExpression* VariableExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) { - // If the name of the variable is a key of the map, we need to replace it. - auto substitutionIterator = substitution.find(variableName); - - if (substitutionIterator != substitution.end()) { - std::unique_ptr<BaseExpression> expressionClone = substitutionIterator->second.get().clone(); - BaseExpression* rawPointer = expressionClone.release(); - return rawPointer; - } else { - // Otherwise, we don't need to replace anything. - return this; - } - } - - void VariableExpression::accept(ExpressionVisitor* visitor) { - visitor->visit(this); - } - - std::string VariableExpression::toString() const { - return this->variableName; - } - - int_fast64_t VariableExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (this->getType() != int_) { - BaseExpression::getValueAsInt(variableValues); - } - - if (variableValues != nullptr) { - return variableValues->second[globalIndex]; - } else { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression involving variables without variable values."; - } - } - - bool VariableExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (this->getType() != bool_) { - BaseExpression::getValueAsBool(variableValues); - } - - if (variableValues != nullptr) { - return variableValues->first[globalIndex]; - } else { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression involving variables without variable values."; - } - } - - double VariableExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const { - if (this->getType() != double_ && this->getType() != int_) { - BaseExpression::getValueAsDouble(variableValues); - } - - // Because only int variables can deliver a double value, we only need to check them. - if (variableValues != nullptr) { - return static_cast<double>(variableValues->second[globalIndex]); - } else { - throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression with variable '" << variableName << "' of type double."; - } - } - - std::string const& VariableExpression::getVariableName() const { - return variableName; - } - - uint_fast64_t VariableExpression::getGlobalVariableIndex() const { - return this->globalIndex; - } - - } // namespace expressions - } // namespace ir -} // namespace storm diff --git a/src/ir/expressions/VariableExpression.h b/src/ir/expressions/VariableExpression.h deleted file mode 100644 index 99358d377..000000000 --- a/src/ir/expressions/VariableExpression.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * VariableExpression.h - * - * Created on: 03.01.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_IR_EXPRESSIONS_VARIABLEEXPRESSION_H_ -#define STORM_IR_EXPRESSIONS_VARIABLEEXPRESSION_H_ - -#include "BaseExpression.h" - -namespace storm { - - // Forward-declare VariableState. - namespace parser { - namespace prismparser { - class VariableState; - } // namespace prismparser - } // namespace parser - - namespace ir { - namespace expressions { - - /*! - * A class representing a variable in the expression tree. - */ - class VariableExpression : public BaseExpression { - public: - /*! - * Creates a variable expression of the given type with the given name. As this variable has no indices - * it is only meant as a dummy and needs to be replaced with a "full" variable expression. - * - * @param type The type of the variable. - * @param variableName The name of the variable. - */ - VariableExpression(ReturnType type, std::string const& variableName); - - /*! - * Creates a variable expression of the given type with the given name and indices. - * - * @param type The type of the variable. - * @param globalIndex The global (i.e. program-wide) index of the variable. - * @param variableName The name of the variable. - */ - VariableExpression(ReturnType type, uint_fast64_t globalIndex, std::string const& variableName); - - /*! - * Copy-constructs from the given expression. - * - * @param variableExpression The expression to copy. - */ - VariableExpression(VariableExpression const& variableExpression); - - virtual std::unique_ptr<BaseExpression> clone() const override; - - virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override; - - virtual void accept(ExpressionVisitor* visitor) override; - - virtual std::string toString() const override; - - virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override; - - /*! - * Retrieves the name of the variable. - * - * @return The name of the variable. - */ - std::string const& getVariableName() const; - - /*! - * Retrieves the global (i.e. program-wide) index of the variable. - * - * @return The global index of the variable. - */ - uint_fast64_t getGlobalVariableIndex() const; - - protected: - virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) override; - - private: - // The global index of the variable. - uint_fast64_t globalIndex; - - // The name of the variable. - std::string variableName; - }; - - } // namespace expressions - } // namespace ir -} // namespace storm - -#endif /* STORM_IR_EXPRESSIONS_VARIABLEEXPRESSION_H_ */ diff --git a/src/parser/PrismParser.cpp b/src/parser/PrismParser.cpp index 587c91dc8..6039c2c11 100644 --- a/src/parser/PrismParser.cpp +++ b/src/parser/PrismParser.cpp @@ -1,128 +1,636 @@ -/* - * PrismParser.cpp - * - * Created on: 11.01.2013 - * Author: chris - */ - -#include "PrismParser.h" - -#include "src/utility/OsDetection.h" - -#include "src/parser/prismparser/PrismGrammar.h" - -// If the parser fails due to ill-formed data, this exception is thrown. +#include "src/parser/PrismParser.h" +#include "src/exceptions/InvalidArgumentException.h" #include "src/exceptions/WrongFormatException.h" -// Needed for file IO. -#include <fstream> -#include <iomanip> -#include <limits> - -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" -extern log4cplus::Logger logger; - - namespace storm { -namespace parser { - -/*! - * Opens the given file for parsing, invokes the helper function to parse the actual content and - * closes the file properly, even if an exception is thrown in the parser. In this case, the - * exception is passed on to the caller. - */ -storm::ir::Program PrismParserFromFile(std::string const& filename) { - // Open file and initialize result. - std::ifstream inputFileStream(filename, std::ios::in); - storm::ir::Program result; - - // Now try to parse the contents of the file. - try { - result = PrismParser(inputFileStream, filename); - } catch(std::exception& e) { - // In case of an exception properly close the file before passing exception. - inputFileStream.close(); - throw e; - } - - // Close the stream in case everything went smoothly and return result. - inputFileStream.close(); - return result; -} - -/*! - * Passes iterators to the input stream to the Boost spirit parser and thereby parses the input. - * If the parser throws an expectation failure exception, i.e. expected input different than the one - * provided, this is caught and displayed properly before the exception is passed on. - */ -storm::ir::Program PrismParser(std::istream& inputStream, std::string const& filename) { - // Prepare iterators to input. - // TODO: Right now, this parses the whole contents of the file into a string first. - // While this is usually not necessary, because there exist adapters that make an input stream - // iterable in both directions without storing it into a string, using the corresponding - // Boost classes gives an awful output under valgrind and is thus disabled for the time being. - std::string fileContent((std::istreambuf_iterator<char>(inputStream)), (std::istreambuf_iterator<char>())); - BaseIteratorType stringIteratorBegin = fileContent.begin(); - BaseIteratorType stringIteratorEnd = fileContent.end(); - PositionIteratorType positionIteratorBegin(stringIteratorBegin, stringIteratorEnd, filename); - PositionIteratorType positionIteratorBegin2(stringIteratorBegin, stringIteratorEnd, filename); - PositionIteratorType positionIteratorEnd; - - // Prepare resulting intermediate representation of input. - storm::ir::Program result; - - // In order to instantiate the grammar, we have to pass the type of the skipping parser. - // As this is more complex, we let Boost figure out the actual type for us. - prism::PrismGrammar grammar; - try { - // Now parse the content using phrase_parse in order to be able to supply a skipping parser. - // First run. - LOG4CPLUS_INFO(logger, "Start parsing..."); - qi::phrase_parse(positionIteratorBegin, positionIteratorEnd, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); - grammar.prepareForSecondRun(); - result = storm::ir::Program(); - LOG4CPLUS_INFO(logger, "Start second parsing run..."); - // Second run. - qi::phrase_parse(positionIteratorBegin2, positionIteratorEnd, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); - LOG4CPLUS_INFO(logger, "Finished parsing, here is the parsed program:" << std::endl << result.toString()); - // Reset grammars. - grammar.resetGrammars(); - } catch(const qi::expectation_failure<PositionIteratorType>& e) { - // If the parser expected content different than the one provided, display information - // about the location of the error. - const boost::spirit::classic::file_position_base<std::string>& pos = e.first.get_position(); - - // Construct the error message including a caret display of the position in the - // erroneous line. - std::stringstream msg; - std::string line = e.first.get_currentline(); - while (line.find('\t') != std::string::npos) line.replace(line.find('\t'),1," "); - msg << pos.file << ", line " << pos.line << ", column " << pos.column - << ": parse error: expected " << e.what_ << std::endl << "\t" - << line << std::endl << "\t"; - int i = 0; - for (i = 1; i < pos.column; ++i) { - msg << "-"; - } - msg << "^"; - for (; i < 80; ++i) { - msg << "-"; - } - msg << std::endl; - - std::cerr << msg.str(); - - // Reset grammars in any case. - grammar.resetGrammars(); - - // Now propagate exception. - throw storm::exceptions::WrongFormatException() << msg.str(); - } - - return result; -} - -} // namespace parser - + namespace parser { + storm::prism::Program PrismParser::parse(std::string const& filename, bool typeCheck) { + // Open file and initialize result. + std::ifstream inputFileStream(filename, std::ios::in); + LOG_THROW(inputFileStream.good(), storm::exceptions::WrongFormatException, "Unable to read from file " << filename << "."); + + storm::prism::Program result; + + // Now try to parse the contents of the file. + try { + std::string fileContent((std::istreambuf_iterator<char>(inputFileStream)), (std::istreambuf_iterator<char>())); + result = parseFromString(fileContent, filename, typeCheck); + } catch(std::exception& e) { + // In case of an exception properly close the file before passing exception. + inputFileStream.close(); + throw e; + } + + // Close the stream in case everything went smoothly and return result. + inputFileStream.close(); + return result; + } + + storm::prism::Program PrismParser::parseFromString(std::string const& input, std::string const& filename, bool typeCheck) { + PositionIteratorType first(input.begin()); + PositionIteratorType iter = first; + PositionIteratorType last(input.end()); + + // Create empty result; + storm::prism::Program result; + + // Create grammar. + storm::parser::PrismParser grammar(filename, first); + try { + // Now parse the content using phrase_parse in order to be able to supply a skipping parser. + bool succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); + LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Parsing failed in first pass."); + if (typeCheck) { + first = PositionIteratorType(input.begin()); + iter = first; + last = PositionIteratorType(input.end()); + grammar.moveToSecondRun(); + succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); + LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Parsing failed in second pass."); + } + } catch (qi::expectation_failure<PositionIteratorType> const& e) { + // If the parser expected content different than the one provided, display information about the location of the error. + std::size_t lineNumber = boost::spirit::get_line(e.first); + + // Now propagate exception. + LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << lineNumber << " of file " << filename << "."); + } + + return result; + } + + PrismParser::PrismParser(std::string const& filename, Iterator first) : PrismParser::base_type(start), secondRun(false), allowDoubleLiteralsFlag(true), filename(filename), annotate(first) { + // Parse simple identifier. + identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][qi::_pass = phoenix::bind(&PrismParser::isValidIdentifier, phoenix::ref(*this), qi::_1)]; + identifier.name("identifier"); + + floorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createFloorExpression, phoenix::ref(*this), qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createCeilExpression, phoenix::ref(*this), qi::_1)]]; + floorCeilExpression.name("floor/ceil expression"); + + minMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(",") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createMinimumExpression, phoenix::ref(*this), qi::_1, qi::_2)] .else_ [qi::_val = phoenix::bind(&PrismParser::createMaximumExpression, phoenix::ref(*this), qi::_1, qi::_2)]]; + minMaxExpression.name("min/max expression"); + + identifierExpression = identifier[qi::_val = phoenix::bind(&PrismParser::getIdentifierExpression, phoenix::ref(*this), qi::_1)]; + identifierExpression.name("identifier expression"); + + literalExpression = qi::lit("true")[qi::_val = phoenix::bind(&PrismParser::createTrueExpression, phoenix::ref(*this))] | qi::lit("false")[qi::_val = phoenix::bind(&PrismParser::createFalseExpression, phoenix::ref(*this))] | strict_double[qi::_val = phoenix::bind(&PrismParser::createDoubleLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)] | qi::int_[qi::_val = phoenix::bind(&PrismParser::createIntegerLiteralExpression, phoenix::ref(*this), qi::_1)]; + literalExpression.name("literal expression"); + + atomicExpression = minMaxExpression | floorCeilExpression | qi::lit("(") >> expression >> qi::lit(")") | literalExpression | identifierExpression; + atomicExpression.name("atomic expression"); + + unaryExpression = atomicExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicExpression)[qi::_val = phoenix::bind(&PrismParser::createNotExpression, phoenix::ref(*this), qi::_1)] | (qi::lit("-") >> atomicExpression)[qi::_val = phoenix::bind(&PrismParser::createMinusExpression, phoenix::ref(*this), qi::_1)]; + unaryExpression.name("unary expression"); + + multiplicationExpression = unaryExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> unaryExpression[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createMultExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createDivExpression, phoenix::ref(*this), qi::_val, qi::_1)]]); + multiplicationExpression.name("multiplication expression"); + + plusExpression = multiplicationExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> multiplicationExpression)[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createPlusExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createMinusExpression, phoenix::ref(*this), qi::_val, qi::_1)]]; + plusExpression.name("plus expression"); + + relativeExpression = (plusExpression >> qi::lit(">=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createGreaterOrEqualExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit(">") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createGreaterExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("<=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createLessOrEqualExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("<") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createLessExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createEqualsExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("!=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createNotEqualsExpression, phoenix::ref(*this), qi::_1, qi::_2)] | plusExpression[qi::_val = qi::_1]; + relativeExpression.name("relative expression"); + + andExpression = relativeExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> relativeExpression)[qi::_val = phoenix::bind(&PrismParser::createAndExpression, phoenix::ref(*this), qi::_val, qi::_1)]; + andExpression.name("and expression"); + + orExpression = andExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> andExpression)[qi::_val = phoenix::bind(&PrismParser::createOrExpression, phoenix::ref(*this), qi::_val, qi::_1)]; + orExpression.name("or expression"); + + iteExpression = orExpression[qi::_val = qi::_1] >> -(qi::lit("?") > orExpression > qi::lit(":") > orExpression)[qi::_val = phoenix::bind(&PrismParser::createIteExpression, phoenix::ref(*this), qi::_val, qi::_1, qi::_2)]; + iteExpression.name("if-then-else expression"); + + expression %= iteExpression; + expression.name("expression"); + + modelTypeDefinition %= modelType_; + modelTypeDefinition.name("model type"); + + undefinedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedBooleanConstant, phoenix::ref(*this), qi::_1)]; + undefinedBooleanConstantDefinition.name("undefined boolean constant declaration"); + + undefinedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedIntegerConstant, phoenix::ref(*this), qi::_1)]; + undefinedIntegerConstantDefinition.name("undefined integer constant declaration"); + + undefinedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedDoubleConstant, phoenix::ref(*this), qi::_1)]; + undefinedDoubleConstantDefinition.name("undefined double constant definition"); + + undefinedConstantDefinition = (undefinedBooleanConstantDefinition | undefinedIntegerConstantDefinition | undefinedDoubleConstantDefinition); + undefinedConstantDefinition.name("undefined constant definition"); + + definedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedBooleanConstant, phoenix::ref(*this), qi::_1, qi::_2)]; + definedBooleanConstantDefinition.name("defined boolean constant declaration"); + + definedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int") >> identifier >> qi::lit("=")) > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedIntegerConstant, phoenix::ref(*this), qi::_1, qi::_2)]; + definedIntegerConstantDefinition.name("defined integer constant declaration"); + + definedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedDoubleConstant, phoenix::ref(*this), qi::_1, qi::_2)]; + definedDoubleConstantDefinition.name("defined double constant declaration"); + + definedConstantDefinition %= (definedBooleanConstantDefinition | definedIntegerConstantDefinition | definedDoubleConstantDefinition); + definedConstantDefinition.name("defined constant definition"); + + formulaDefinition = (qi::lit("formula") > identifier > qi::lit("=") > expression > 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") > expression) | qi::attr(storm::expressions::Expression::createFalse())) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createBooleanVariable, phoenix::ref(*this), qi::_1, qi::_2)]; + booleanVariableDefinition.name("boolean variable definition"); + + integerVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("[")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), false)]) > expression[qi::_a = qi::_1] > qi::lit("..") > expression > qi::lit("]")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), true)] > -(qi::lit("init") > expression[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)]); + variableDefinition.name("variable declaration"); + + globalVariableDefinition = (qi::lit("global") > (booleanVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalBooleanVariables, qi::_r1), qi::_1)] | integerVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalIntegerVariables, qi::_r1), qi::_1)])); + globalVariableDefinition.name("global variable declaration list"); + + programHeader = modelTypeDefinition[phoenix::bind(&GlobalProgramInformation::modelType, qi::_r1) = qi::_1] + > *(definedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)] | undefinedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)]) + > *(formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_r1), qi::_1)]) + > *(globalVariableDefinition(qi::_r1)); + programHeader.name("program header"); + + stateRewardDefinition = (expression > qi::lit(":") > plusExpression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createStateReward, phoenix::ref(*this), qi::_1, qi::_2)]; + stateRewardDefinition.name("state reward definition"); + + transitionRewardDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit(":") > plusExpression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createTransitionReward, phoenix::ref(*this), qi::_a, qi::_2, qi::_3)]; + transitionRewardDefinition.name("transition reward definition"); + + rewardModelDefinition = (qi::lit("rewards") > -(qi::lit("\"") > identifier[qi::_a = qi::_1] > qi::lit("\"")) + > +( stateRewardDefinition[phoenix::push_back(qi::_b, qi::_1)] + | transitionRewardDefinition[phoenix::push_back(qi::_c, qi::_1)] + ) + >> qi::lit("endrewards"))[qi::_val = phoenix::bind(&PrismParser::createRewardModel, phoenix::ref(*this), qi::_a, qi::_b, qi::_c)]; + rewardModelDefinition.name("reward model definition"); + + initialStatesConstruct = (qi::lit("init") > expression > qi::lit("endinit"))[qi::_pass = phoenix::bind(&PrismParser::addInitialStatesExpression, phoenix::ref(*this), qi::_1, qi::_r1)]; + initialStatesConstruct.name("initial construct"); + + labelDefinition = (qi::lit("label") > -qi::lit("\"") > identifier > -qi::lit("\"") > qi::lit("=") > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createLabel, phoenix::ref(*this), qi::_1, qi::_2)]; + labelDefinition.name("label definition"); + + assignmentDefinition = (qi::lit("(") > identifier > qi::lit("'") > qi::lit("=") > expression > qi::lit(")"))[qi::_val = phoenix::bind(&PrismParser::createAssignment, phoenix::ref(*this), qi::_1, qi::_2)]; + assignmentDefinition.name("assignment"); + + assignmentDefinitionList %= +assignmentDefinition % "&"; + assignmentDefinitionList.name("assignment list"); + + updateDefinition = (((plusExpression > qi::lit(":")) | qi::attr(storm::expressions::Expression::createDoubleLiteral(1))) >> assignmentDefinitionList)[qi::_val = phoenix::bind(&PrismParser::createUpdate, phoenix::ref(*this), qi::_1, qi::_2, qi::_r1)]; + updateDefinition.name("update"); + + updateListDefinition %= +updateDefinition(qi::_r1) % "+"; + updateListDefinition.name("update list"); + + commandDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit("->") > updateListDefinition(qi::_r1) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createCommand, phoenix::ref(*this), qi::_a, qi::_2, qi::_3, qi::_r1)]; + commandDefinition.name("command definition"); + + moduleDefinition = ((qi::lit("module") >> identifier >> *(variableDefinition(qi::_a, qi::_b))) > +commandDefinition(qi::_r1) > qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismParser::createModule, phoenix::ref(*this), qi::_1, qi::_a, qi::_b, qi::_2, qi::_r1)]; + moduleDefinition.name("module definition"); + + moduleRenaming = ((qi::lit("module") >> identifier >> qi::lit("=")) > identifier > qi::lit("[") + > ((identifier > qi::lit("=") > identifier)[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string,std::string>>(qi::_1, qi::_2))] % ",") > qi::lit("]") + > qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismParser::createRenamedModule, phoenix::ref(*this), qi::_1, qi::_2, qi::_a, qi::_r1)]; + moduleRenaming.name("module definition via renaming"); + + 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 > programHeader(qi::_a) > moduleDefinitionList(qi::_a) > *(initialStatesConstruct(qi::_a) | rewardModelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::rewardModels, qi::_a), qi::_1)] | labelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::labels, qi::_a), qi::_1)] | formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_a), qi::_1)]) > qi::eoi)[qi::_val = phoenix::bind(&PrismParser::createProgram, phoenix::ref(*this), qi::_a)]; + start.name("probabilistic program"); + + // Enable error reporting. + qi::on_error<qi::fail>(expression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(iteExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(orExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(andExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(relativeExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(plusExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(multiplicationExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(unaryExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(atomicExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(literalExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(identifierExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(minMaxExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error<qi::fail>(floorCeilExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + + // Enable location tracking for important entities. + auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3); + qi::on_success(undefinedBooleanConstantDefinition, setLocationInfoFunction); + qi::on_success(undefinedIntegerConstantDefinition, setLocationInfoFunction); + qi::on_success(undefinedDoubleConstantDefinition, setLocationInfoFunction); + qi::on_success(definedBooleanConstantDefinition, setLocationInfoFunction); + qi::on_success(definedIntegerConstantDefinition, setLocationInfoFunction); + qi::on_success(definedDoubleConstantDefinition, setLocationInfoFunction); + qi::on_success(booleanVariableDefinition, setLocationInfoFunction); + qi::on_success(integerVariableDefinition, setLocationInfoFunction); + qi::on_success(moduleDefinition, setLocationInfoFunction); + qi::on_success(moduleRenaming, setLocationInfoFunction); + qi::on_success(formulaDefinition, setLocationInfoFunction); + qi::on_success(rewardModelDefinition, setLocationInfoFunction); + qi::on_success(labelDefinition, setLocationInfoFunction); + qi::on_success(commandDefinition, setLocationInfoFunction); + qi::on_success(updateDefinition, setLocationInfoFunction); + qi::on_success(assignmentDefinition, setLocationInfoFunction); + } + + void PrismParser::moveToSecondRun() { + this->secondRun = true; + } + + void PrismParser::allowDoubleLiterals(bool flag) { + this->allowDoubleLiteralsFlag = flag; + } + + std::string const& PrismParser::getFilename() const { + return this->filename; + } + + bool PrismParser::isValidIdentifier(std::string const& identifier) { + if (this->keywords_.find(identifier) != nullptr) { + return false; + } + return true; + } + + bool PrismParser::addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation) { + LOG_THROW(!globalProgramInformation.hasInitialStatesExpression, storm::exceptions::InvalidArgumentException, "Program must not define two initial constructs."); + if (globalProgramInformation.hasInitialStatesExpression) { + return false; + } + globalProgramInformation.hasInitialStatesExpression = true; + globalProgramInformation.initialStatesExpression = initialStatesExpression; + return true; + } + + storm::expressions::Expression PrismParser::createIteExpression(storm::expressions::Expression e1, storm::expressions::Expression e2, storm::expressions::Expression e3) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1.ite(e2, e3); + } + } + + storm::expressions::Expression PrismParser::createOrExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 || e2; + } + } + + storm::expressions::Expression PrismParser::createAndExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 && e2; + } + } + + storm::expressions::Expression PrismParser::createGreaterExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 > e2; + } + } + + storm::expressions::Expression PrismParser::createGreaterOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 >= e2; + } + } + + storm::expressions::Expression PrismParser::createLessExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 < e2; + } + } + + storm::expressions::Expression PrismParser::createLessOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 <= e2; + } + } + + storm::expressions::Expression PrismParser::createEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 == e2; + } + } + + storm::expressions::Expression PrismParser::createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 != e2; + } + } + + storm::expressions::Expression PrismParser::createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 + e2; + } + } + + storm::expressions::Expression PrismParser::createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 - e2; + } + } + + storm::expressions::Expression PrismParser::createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 * e2; + } + } + + storm::expressions::Expression PrismParser::createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1 / e2; + } + } + + storm::expressions::Expression PrismParser::createNotExpression(storm::expressions::Expression e1) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return !e1; + } + } + + storm::expressions::Expression PrismParser::createMinusExpression(storm::expressions::Expression e1) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return -e1; + } + } + + storm::expressions::Expression PrismParser::createTrueExpression() const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return storm::expressions::Expression::createTrue(); + } + } + + storm::expressions::Expression PrismParser::createFalseExpression() const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return storm::expressions::Expression::createFalse(); + } + } + + storm::expressions::Expression PrismParser::createDoubleLiteralExpression(double value, bool& pass) const { + // If we are not supposed to accept double expressions, we reject it by setting pass to false. + if (!this->allowDoubleLiteralsFlag) { + pass = false; + } + + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return storm::expressions::Expression::createDoubleLiteral(value); + } + } + + storm::expressions::Expression PrismParser::createIntegerLiteralExpression(int value) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return storm::expressions::Expression::createIntegerLiteral(static_cast<int_fast64_t>(value)); + } + } + + storm::expressions::Expression PrismParser::createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return storm::expressions::Expression::minimum(e1, e2); + } + } + + storm::expressions::Expression PrismParser::createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return storm::expressions::Expression::maximum(e1, e2); + } + } + + storm::expressions::Expression PrismParser::createFloorExpression(storm::expressions::Expression e1) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1.floor(); + } + } + + storm::expressions::Expression PrismParser::createCeilExpression(storm::expressions::Expression e1) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + return e1.ceil(); + } + } + + storm::expressions::Expression PrismParser::getIdentifierExpression(std::string const& identifier) const { + if (!this->secondRun) { + return storm::expressions::Expression::createFalse(); + } else { + storm::expressions::Expression const* expression = this->identifiers_.find(identifier); + LOG_THROW(expression != nullptr, storm::exceptions::WrongFormatException, "Undeclared identifier '" << identifier << "'."); + return *expression; + } + } + + storm::prism::Constant PrismParser::createUndefinedBooleanConstant(std::string const& newConstant) const { + this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant)); + return storm::prism::Constant(storm::expressions::ExpressionReturnType::Bool, newConstant, this->getFilename()); + } + + storm::prism::Constant PrismParser::createUndefinedIntegerConstant(std::string const& newConstant) const { + this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant)); + return storm::prism::Constant(storm::expressions::ExpressionReturnType::Int, newConstant, this->getFilename()); + } + + storm::prism::Constant PrismParser::createUndefinedDoubleConstant(std::string const& newConstant) const { + this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant)); + return storm::prism::Constant(storm::expressions::ExpressionReturnType::Double, newConstant, this->getFilename()); + } + + storm::prism::Constant PrismParser::createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const { + this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant)); + return storm::prism::Constant(storm::expressions::ExpressionReturnType::Bool, newConstant, expression, this->getFilename()); + } + + storm::prism::Constant PrismParser::createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const { + this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant)); + return storm::prism::Constant(storm::expressions::ExpressionReturnType::Int, newConstant, expression, this->getFilename()); + } + + storm::prism::Constant PrismParser::createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const { + this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant)); + return storm::prism::Constant(storm::expressions::ExpressionReturnType::Double, newConstant, expression, this->getFilename()); + } + + storm::prism::Formula PrismParser::createFormula(std::string const& formulaName, storm::expressions::Expression expression) const { + if (this->secondRun) { + this->identifiers_.add(formulaName, expression); + } + return storm::prism::Formula(formulaName, expression, this->getFilename()); + } + + storm::prism::Label PrismParser::createLabel(std::string const& labelName, storm::expressions::Expression expression) const { + return storm::prism::Label(labelName, expression, this->getFilename()); + } + + storm::prism::RewardModel PrismParser::createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const { + return storm::prism::RewardModel(rewardModelName, stateRewards, transitionRewards, this->getFilename()); + } + + storm::prism::StateReward PrismParser::createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const { + return storm::prism::StateReward(statePredicateExpression, rewardValueExpression, this->getFilename()); + } + + storm::prism::TransitionReward PrismParser::createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const { + return storm::prism::TransitionReward(actionName, statePredicateExpression, rewardValueExpression, this->getFilename()); + } + + storm::prism::Assignment PrismParser::createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const { + return storm::prism::Assignment(variableName, assignedExpression, this->getFilename()); + } + + storm::prism::Update PrismParser::createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const { + ++globalProgramInformation.currentUpdateIndex; + return storm::prism::Update(globalProgramInformation.currentUpdateIndex - 1, likelihoodExpression, assignments, this->getFilename()); + } + + storm::prism::Command PrismParser::createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const { + ++globalProgramInformation.currentCommandIndex; + return storm::prism::Command(globalProgramInformation.currentCommandIndex - 1, actionName, guardExpression, updates, this->getFilename()); + } + + storm::prism::BooleanVariable PrismParser::createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const { + this->identifiers_.add(variableName, storm::expressions::Expression::createBooleanVariable(variableName)); + return storm::prism::BooleanVariable(variableName, initialValueExpression, this->getFilename()); + } + + storm::prism::IntegerVariable PrismParser::createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const { + this->identifiers_.add(variableName, storm::expressions::Expression::createIntegerVariable(variableName)); + return storm::prism::IntegerVariable(variableName, lowerBoundExpression, upperBoundExpression, initialValueExpression, this->getFilename()); + } + + storm::prism::Module PrismParser::createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const { + globalProgramInformation.moduleToIndexMap[moduleName] = globalProgramInformation.modules.size(); + return storm::prism::Module(moduleName, booleanVariables, integerVariables, commands, this->getFilename()); + } + + storm::prism::Module PrismParser::createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const { + // Check whether the module to rename actually exists. + auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName); + LOG_THROW(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(), storm::exceptions::WrongFormatException, "No module named '" << oldModuleName << "' to rename."); + storm::prism::Module const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second]; + + if (!this->secondRun) { + // Register all (renamed) variables for later use. + for (auto const& variable : moduleToRename.getBooleanVariables()) { + auto const& renamingPair = renaming.find(variable.getName()); + LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Boolean variable '" << variable.getName() << " was not renamed."); + this->identifiers_.add(renamingPair->second, storm::expressions::Expression::createBooleanVariable(renamingPair->second)); + } + for (auto const& variable : moduleToRename.getIntegerVariables()) { + auto const& renamingPair = renaming.find(variable.getName()); + LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Integer variable '" << variable.getName() << " was not renamed."); + this->identifiers_.add(renamingPair->second, storm::expressions::Expression::createIntegerVariable(renamingPair->second)); + } + + // Return a dummy module in the first pass. + return storm::prism::Module(); + } else { + // Add a mapping from the new module name to its (future) index. + globalProgramInformation.moduleToIndexMap[newModuleName] = globalProgramInformation.modules.size(); + + // Create a mapping from identifiers to the expressions they need to be replaced with. + std::map<std::string, storm::expressions::Expression> expressionRenaming; + for (auto const& namePair : renaming) { + storm::expressions::Expression const* substitutedExpression = this->identifiers_.find(namePair.second); + // If the mapped-to-value is an expression, we need to replace it. + if (substitutedExpression != nullptr) { + expressionRenaming.emplace(namePair.first, *substitutedExpression); + } + } + + // Rename the boolean variables. + std::vector<storm::prism::BooleanVariable> booleanVariables; + for (auto const& variable : moduleToRename.getBooleanVariables()) { + auto const& renamingPair = renaming.find(variable.getName()); + LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Boolean variable '" << variable.getName() << " was not renamed."); + + booleanVariables.push_back(storm::prism::BooleanVariable(renamingPair->second, variable.getInitialValueExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1))); + } + + // Rename the integer variables. + std::vector<storm::prism::IntegerVariable> integerVariables; + for (auto const& variable : moduleToRename.getIntegerVariables()) { + auto const& renamingPair = renaming.find(variable.getName()); + LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Integer variable '" << variable.getName() << " was not renamed."); + + integerVariables.push_back(storm::prism::IntegerVariable(renamingPair->second, variable.getLowerBoundExpression().substitute<std::map>(expressionRenaming), variable.getUpperBoundExpression().substitute<std::map>(expressionRenaming), variable.getInitialValueExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1))); + } + + // Rename commands. + std::vector<storm::prism::Command> commands; + for (auto const& command : moduleToRename.getCommands()) { + std::vector<storm::prism::Update> updates; + for (auto const& update : command.getUpdates()) { + std::vector<storm::prism::Assignment> assignments; + for (auto const& assignment : update.getAssignments()) { + auto const& renamingPair = renaming.find(assignment.getVariableName()); + if (renamingPair != renaming.end()) { + assignments.emplace_back(renamingPair->second, assignment.getExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1)); + } else { + assignments.emplace_back(assignment.getVariableName(), assignment.getExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1)); + } + } + updates.emplace_back(globalProgramInformation.currentUpdateIndex, update.getLikelihoodExpression().substitute<std::map>(expressionRenaming), assignments, this->getFilename(), get_line(qi::_1)); + ++globalProgramInformation.currentUpdateIndex; + } + + std::string newActionName = command.getActionName(); + auto const& renamingPair = renaming.find(command.getActionName()); + if (renamingPair != renaming.end()) { + newActionName = renamingPair->second; + } + + commands.emplace_back(globalProgramInformation.currentCommandIndex, newActionName, command.getGuardExpression().substitute<std::map>(expressionRenaming), updates, this->getFilename(), get_line(qi::_1)); + ++globalProgramInformation.currentCommandIndex; + } + + return storm::prism::Module(newModuleName, booleanVariables, integerVariables, commands, this->getFilename()); + } + } + + storm::prism::Program PrismParser::createProgram(GlobalProgramInformation const& globalProgramInformation) const { + return storm::prism::Program(globalProgramInformation.modelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables, globalProgramInformation.globalIntegerVariables, globalProgramInformation.formulas, globalProgramInformation.modules, globalProgramInformation.rewardModels, globalProgramInformation.hasInitialStatesExpression, globalProgramInformation.initialStatesExpression, globalProgramInformation.labels, this->getFilename()); + } + } // namespace parser } // namespace storm diff --git a/src/parser/PrismParser.h b/src/parser/PrismParser.h index da8ad0941..3f8f17b65 100644 --- a/src/parser/PrismParser.h +++ b/src/parser/PrismParser.h @@ -1,49 +1,320 @@ -/* * PrismParser.h - * - * Created on: Jan 3, 2013 - * Author: Christian Dehnert - */ - #ifndef STORM_PARSER_PRISMPARSER_H_ -#define STORM_PARSER_PRISMPARSER_H_ - -// All classes of the intermediate representation are used. -#include "src/ir/IR.h" +#define STORM_PARSER_PRISMPARSER_H_ -// Used for file input. -#include <istream> +// Include files for file input. +#include <fstream> #include <memory> +#include <iomanip> -namespace storm { - -namespace parser { +// Include boost spirit. +#define BOOST_SPIRIT_USE_PHOENIX_V3 +#include <boost/typeof/typeof.hpp> +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix.hpp> +#include <boost/spirit/include/support_line_pos_iterator.hpp> +#include <boost/spirit/home/classic/iterator/position_iterator.hpp> -using namespace storm::ir; -using namespace storm::ir::expressions; +namespace qi = boost::spirit::qi; +namespace phoenix = boost::phoenix; -/* - * This functions parse the format of the PRISM model checker into an intermediate representation. - */ +typedef std::string::const_iterator BaseIteratorType; +typedef boost::spirit::line_pos_iterator<BaseIteratorType> PositionIteratorType; +typedef PositionIteratorType Iterator; +typedef BOOST_TYPEOF(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol) Skipper; +typedef BOOST_TYPEOF(qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol | boost::spirit::ascii::space) Skipper2; -/*! - * Parses the given file into the intermediate representation assuming it complies with the - * PRISM syntax. - * @param filename the name of the file to parse. - * @return a shared pointer to the intermediate representation of the PRISM file. - */ -storm::ir::Program PrismParserFromFile(std::string const& filename); +#include "src/storage/prism/Program.h" +#include "src/storage/expressions/Expression.h" +#include "src/exceptions/ExceptionMacros.h" -/*! - * Parses the given input stream into the intermediate representation assuming it complies with - * the PRISM syntax. - * @param inputStream the input stream to parse. - * @param filename the name of the file the input stream belongs to. Used for diagnostics. - * @return a shared pointer to the intermediate representation of the PRISM file. - */ -storm::ir::Program PrismParser(std::istream& inputStream, std::string const& filename); - -} // namespace parser +namespace storm { + namespace parser { + class GlobalProgramInformation { + public: + // Default construct the header information. + GlobalProgramInformation() = default; + + // Members for all essential information that needs to be collected. + storm::prism::Program::ModelType modelType; + std::vector<storm::prism::Constant> constants; + std::vector<storm::prism::Formula> formulas; + std::vector<storm::prism::BooleanVariable> globalBooleanVariables; + std::vector<storm::prism::IntegerVariable> globalIntegerVariables; + std::map<std::string, uint_fast64_t> moduleToIndexMap; + std::vector<storm::prism::Module> modules; + std::vector<storm::prism::RewardModel> rewardModels; + std::vector<storm::prism::Label> labels; + storm::expressions::Expression initialStatesExpression; + bool hasInitialStatesExpression; + + // Counters to provide unique indexing for commands and updates. + uint_fast64_t currentCommandIndex; + uint_fast64_t currentUpdateIndex; + }; + class PrismParser : public qi::grammar<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> { + public: + /*! + * Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax. + * + * @param filename the name of the file to parse. + * @param typeCheck Sets whether the expressions are generated and therefore typechecked. + * @return The resulting PRISM program. + */ + static storm::prism::Program parse(std::string const& filename, bool typeCheck = true); + + /*! + * Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM syntax. + * + * @param input The input string to parse. + * @param filename The name of the file from which the input was read. + * @param typeCheck Sets whether the expressions are generated and therefore typechecked. + * @return The resulting PRISM program. + */ + static storm::prism::Program parseFromString(std::string const& input, std::string const& filename, bool typeCheck = true); + + private: + struct modelTypeStruct : qi::symbols<char, storm::prism::Program::ModelType> { + modelTypeStruct() { + add + ("dtmc", storm::prism::Program::ModelType::DTMC) + ("ctmc", storm::prism::Program::ModelType::CTMC) + ("mdp", storm::prism::Program::ModelType::MDP) + ("ctmdp", storm::prism::Program::ModelType::CTMDP) + ("ma", storm::prism::Program::ModelType::MA); + } + }; + + struct keywordsStruct : qi::symbols<char, bool> { + keywordsStruct() { + add + ("dtmc", 1) + ("ctmc", 2) + ("mdp", 3) + ("ctmdp", 4) + ("ma", 5) + ("const", 6) + ("int", 7) + ("bool", 8) + ("module", 9) + ("endmodule", 10) + ("rewards", 11) + ("endrewards", 12) + ("true", 13) + ("min", 14) + ("max", 15) + ("floor", 16) + ("ceil", 17) + ("init", 18) + ("endinit", 19); + } + }; + + // Functor used for displaying error information. + struct ErrorHandler { + typedef qi::error_handler_result result_type; + + template<typename T1, typename T2, typename T3, typename T4> + qi::error_handler_result operator()(T1 b, T2 e, T3 where, T4 const& what) const { + // LOG4CPLUS_ERROR(logger, "Error: expecting " << what << " in line " << get_line(where) << " at column " << get_column(b, where, 4) << "."); + std::cerr << "Error: expecting " << what << " in line " << get_line(where) << "." << std::endl; + T3 end(where); + while (end != e && *end != '\r' && *end != '\n') { + ++end; + } + std::cerr << "Error: expecting " << what << " in line " << get_line(where) << ": \n" << std::string(get_line_start(b, where), end) << " ... \n" << std::setw(std::distance(b, where)) << '^' << "---- here\n"; + return qi::fail; + } + }; + + // Functor used for annotating entities with line number information. + class PositionAnnotation { + public: + typedef void result_type; + + PositionAnnotation(Iterator first) : first(first) { + // Intentionally left empty. + } + + template<typename Entity, typename First, typename Last> + result_type operator()(Entity& entity, First f, Last l) const { + entity.setLineNumber(get_line(f)); + } + private: + std::string filename; + Iterator const first; + }; + + /*! + * Creates a grammar for the given filename and the iterator to the first input to parse. + * + * @param filename The filename that is to be read. This is used for proper error reporting. + * @param first The iterator to the beginning of the input. + */ + PrismParser(std::string const& filename, Iterator first); + + /*! + * Sets an internal flag that indicates the second run is now taking place. + */ + void moveToSecondRun(); + + // A flag that stores whether the grammar is currently doing the second run. + bool secondRun; + + /*! + * Sets whether doubles literals are allowed in the parsed expression. + * + * @param flag Indicates whether to allow or forbid double literals in the parsed expression. + */ + void allowDoubleLiterals(bool flag); + + // A flag that stores wether to allow or forbid double literals in parsed expressions. + bool allowDoubleLiteralsFlag; + + // The name of the file being parsed. + std::string filename; + + /*! + * Retrieves the name of the file currently being parsed. + * + * @return The name of the file currently being parsed. + */ + std::string const& getFilename() const; + + // A function used for annotating the entities with their position. + phoenix::function<ErrorHandler> handler; + phoenix::function<PositionAnnotation> annotate; + + // The starting point of the grammar. + qi::rule<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> start; + + // Rules for model type. + qi::rule<Iterator, storm::prism::Program::ModelType(), Skipper> modelTypeDefinition; + + // Rules for parsing the program header. + qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> programHeader; + qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedConstantDefinition; + qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedBooleanConstantDefinition; + qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedIntegerConstantDefinition; + qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedDoubleConstantDefinition; + qi::rule<Iterator, storm::prism::Constant(), Skipper> definedConstantDefinition; + qi::rule<Iterator, storm::prism::Constant(), Skipper> definedBooleanConstantDefinition; + qi::rule<Iterator, storm::prism::Constant(), Skipper> definedIntegerConstantDefinition; + qi::rule<Iterator, storm::prism::Constant(), Skipper> definedDoubleConstantDefinition; + + // Rules for global variable definitions. + qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalVariableDefinition; + qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalBooleanVariableDefinition; + qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalIntegerVariableDefinition; + + // Rules for modules definition. + qi::rule<Iterator, std::vector<storm::prism::Module>(GlobalProgramInformation&), Skipper> moduleDefinitionList; + qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::vector<storm::prism::BooleanVariable>, std::vector<storm::prism::IntegerVariable>>, Skipper> moduleDefinition; + qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming; + + // 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::IntegerVariable(), qi::locals<storm::expressions::Expression>, Skipper> integerVariableDefinition; + + // Rules for command definitions. + qi::rule<Iterator, storm::prism::Command(GlobalProgramInformation&), qi::locals<std::string>, Skipper> commandDefinition; + qi::rule<Iterator, std::vector<storm::prism::Update>(GlobalProgramInformation&), Skipper> updateListDefinition; + qi::rule<Iterator, storm::prism::Update(GlobalProgramInformation&), Skipper> updateDefinition; + qi::rule<Iterator, std::vector<storm::prism::Assignment>(), Skipper> assignmentDefinitionList; + qi::rule<Iterator, storm::prism::Assignment(), Skipper> assignmentDefinition; + + // Rules for reward definitions. + qi::rule<Iterator, storm::prism::RewardModel(), qi::locals<std::string, std::vector<storm::prism::StateReward>, std::vector<storm::prism::TransitionReward>>, Skipper> rewardModelDefinition; + qi::rule<Iterator, storm::prism::StateReward(), Skipper> stateRewardDefinition; + qi::rule<Iterator, storm::prism::TransitionReward(), qi::locals<std::string>, Skipper> transitionRewardDefinition; + + // Rules for initial states expression. + qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> initialStatesConstruct; + + // Rules for label definitions. + qi::rule<Iterator, storm::prism::Label(), Skipper> labelDefinition; + + // Rules for formula definitions. + qi::rule<Iterator, storm::prism::Formula(), Skipper> formulaDefinition; + + // Rules for identifier parsing. + qi::rule<Iterator, std::string(), Skipper> identifier; + + // Rules for parsing a composed expression. + qi::rule<Iterator, storm::expressions::Expression(), Skipper> expression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> iteExpression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> orExpression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> andExpression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> relativeExpression; + qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> plusExpression; + qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> multiplicationExpression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> unaryExpression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicExpression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> literalExpression; + qi::rule<Iterator, storm::expressions::Expression(), Skipper> identifierExpression; + qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> minMaxExpression; + qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> floorCeilExpression; + + // 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; + + // Parsers that recognize special keywords and model types. + storm::parser::PrismParser::keywordsStruct keywords_; + storm::parser::PrismParser::modelTypeStruct modelType_; + qi::symbols<char, storm::expressions::Expression> identifiers_; + + // Helper methods used in the grammar. + bool isValidIdentifier(std::string const& identifier); + bool addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation); + + storm::expressions::Expression createIteExpression(storm::expressions::Expression e1, storm::expressions::Expression e2, storm::expressions::Expression e3) const; + storm::expressions::Expression createOrExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createAndExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createGreaterExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createGreaterOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createLessExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createLessOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createNotExpression(storm::expressions::Expression e1) const; + storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1) const; + storm::expressions::Expression createTrueExpression() const; + storm::expressions::Expression createFalseExpression() const; + storm::expressions::Expression createDoubleLiteralExpression(double value, bool& pass) const; + storm::expressions::Expression createIntegerLiteralExpression(int value) const; + storm::expressions::Expression createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; + storm::expressions::Expression createFloorExpression(storm::expressions::Expression e1) const; + storm::expressions::Expression createCeilExpression(storm::expressions::Expression e1) const; + storm::expressions::Expression getIdentifierExpression(std::string const& identifier) const; + + storm::prism::Constant createUndefinedBooleanConstant(std::string const& newConstant) const; + storm::prism::Constant createUndefinedIntegerConstant(std::string const& newConstant) const; + storm::prism::Constant createUndefinedDoubleConstant(std::string const& newConstant) const; + storm::prism::Constant createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const; + storm::prism::Constant createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const; + storm::prism::Constant createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const; + storm::prism::Formula createFormula(std::string const& formulaName, storm::expressions::Expression expression) const; + storm::prism::Label createLabel(std::string const& labelName, storm::expressions::Expression expression) const; + storm::prism::RewardModel createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const; + storm::prism::StateReward createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const; + storm::prism::TransitionReward createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const; + storm::prism::Assignment createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const; + storm::prism::Update createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const; + storm::prism::Command createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const; + storm::prism::BooleanVariable createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const; + storm::prism::IntegerVariable createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const; + storm::prism::Module createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const; + 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; + }; + } // namespace parser } // namespace storm -#endif /* STORM_PARSER_PRISMPARSER_H_ */ +#endif /* STORM_PARSER_PRISMPARSER_H_ */ + diff --git a/src/parser/prismparser/BaseGrammar.h b/src/parser/prismparser/BaseGrammar.h deleted file mode 100644 index 7cac493c3..000000000 --- a/src/parser/prismparser/BaseGrammar.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * File: Keywords.h - * Author: nafur - * - * Created on April 10, 2013, 6:03 PM - */ - -#ifndef BASEGRAMMAR_H -#define BASEGRAMMAR_H - -#include "Includes.h" - -#include "VariableState.h" - -namespace storm { -namespace parser { -namespace prism { - - /*! - * This is the base class for all expression grammars. - * It takes care of implementing a singleton, stores a VariableState and implements some common helper routines. - */ - template <typename T> - class BaseGrammar { - public: - /*! - * Constructor. - */ - BaseGrammar(std::shared_ptr<VariableState> const& state) : state(state) {} - - /*! - * Create and return a new instance of class T, usually the subclass. - * @param state VariableState to be given to the constructor. - * @returns Instance of class T. - */ - static T& instance(std::shared_ptr<VariableState> const& state = nullptr) { - if (BaseGrammar::instanceObject == nullptr) { - BaseGrammar::instanceObject = std::shared_ptr<T>(new T(state)); - if (!state->firstRun) BaseGrammar::instanceObject->secondRun(); - } - return *BaseGrammar::instanceObject; - } - - /*! - * Clear the cached instance. - */ - static void resetInstance() { - BaseGrammar::instanceObject = nullptr; - } - - /*! - * Notify the cached object, that we will begin with the second parsing run. - */ - static void secondRun() { - if (BaseGrammar::instanceObject != nullptr) { - BaseGrammar::instanceObject->prepareSecondRun(); - } - } - - /*! - * Create a new boolean literal with the given value. - * @param value Value of the literal. - * @returns Boolean literal. - */ - std::shared_ptr<BaseExpression> createBoolLiteral(bool value) { - return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(value)); - } - /*! - * Create a new double literal with the given value. - * @param value Value of the literal. - * @returns Double literal. - */ - std::shared_ptr<BaseExpression> createDoubleLiteral(double value) { - return std::shared_ptr<BaseExpression>(new DoubleLiteralExpression(value)); - } - /*! - * Create a new integer literal with the given value. - * @param value Value of the literal. - * @returns Integer literal. - */ - std::shared_ptr<BaseExpression> createIntLiteral(int_fast64_t value) { - return std::shared_ptr<BaseExpression>(new IntegerLiteralExpression(value)); - } - - /*! - * Create a new plus expression. If addition is true, it will be an addition, otherwise a subtraction. - * @param left Left operand. - * @param addition Flag for addition or subtraction. - * @param right Right operand. - * @param type Return type. - * @returns Plus expression. - */ - std::shared_ptr<BaseExpression> createPlus(std::shared_ptr<BaseExpression> const& left, bool addition, std::shared_ptr<BaseExpression> const& right, BaseExpression::ReturnType type) { - if (addition) { - return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(type, left->clone(), right->clone(), BinaryNumericalFunctionExpression::PLUS)); - } else { - return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(type, left->clone(), right->clone(), BinaryNumericalFunctionExpression::MINUS)); - } - } - /*! - * Create a new double plus expression. If addition is true, it will be an addition, otherwise a subtraction. - * @param left Left operand. - * @param addition Flag for addition or subtraction. - * @param right Right operand. - * @returns Double plus expression. - */ - std::shared_ptr<BaseExpression> createDoublePlus(std::shared_ptr<BaseExpression> const& left, bool addition, std::shared_ptr<BaseExpression> const& right) { - return this->createPlus(left, addition, right, BaseExpression::double_); - } - /*! - * Create a new integer plus expression. If addition is true, it will be an addition, otherwise a subtraction. - * @param left Left operand. - * @param addition Flag for addition or subtraction. - * @param right Right operand. - * @returns Integer plus expression. - */ - std::shared_ptr<BaseExpression> createIntPlus(std::shared_ptr<BaseExpression> const& left, bool addition, std::shared_ptr<BaseExpression> const& right) { - return this->createPlus(left, addition, right, BaseExpression::int_); - } - - /*! - * Create a new integer multiplication expression. - * @param left Left operand. - * @param right Right operand. - * @returns Integer multiplication expression. - */ - std::shared_ptr<BaseExpression> createIntMult(std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) { - return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::int_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::TIMES)); - } - - /*! - * Create a new integer multiplication expression. If multiplication is true, it will be an multiplication, otherwise a division. - * @param left Left operand. - * @param addition Flag for multiplication or division. - * @param right Right operand. - * @returns Integer multiplication expression. - */ - std::shared_ptr<BaseExpression> createDoubleMult(std::shared_ptr<BaseExpression> const& left, bool multiplication, std::shared_ptr<BaseExpression> const& right) { - if (multiplication) { - return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::double_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::TIMES)); - } else { - return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::double_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::DIVIDE)); - } - } - - /*! - * Creates an integer min/max expression. - * - * @param min Indicates whether the expression is min or max. - * @param left The left operand. - * @param right The right operand. - * @return An integer min/max expression. - */ - std::shared_ptr<BaseExpression> createIntMinMax(bool min, std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) { - if (min) { - return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::int_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::MIN)); - } else { - return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::int_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::MAX)); - } - } - - /*! - * Creates an integer floor/ceil expression. - * - * @param floor Indicates whether the expression is a floor expression. - * @param operand The argument of the floor/ceil operation. - * @return An integer floor/ceil expression. - */ - std::shared_ptr<BaseExpression> createIntFloorCeil(bool floor, std::shared_ptr<BaseExpression> const& operand) { - if (floor) { - return std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(BaseExpression::int_, operand->clone(), UnaryNumericalFunctionExpression::FLOOR)); - } else { - return std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(BaseExpression::int_, operand->clone(), UnaryNumericalFunctionExpression::CEIL)); - } - } - - /*! - * Create a new binary relation expression. - * @param left Left operand. - * @param relationType Type of binary relation. - * @param right Right operand. - * @returns Binary relation expression. - */ - std::shared_ptr<BaseExpression> createRelation(std::shared_ptr<BaseExpression> const& left, BinaryRelationExpression::RelationType relationType, std::shared_ptr<BaseExpression> const& right) { - return std::shared_ptr<BaseExpression>(new BinaryRelationExpression(left->clone(), right->clone(), relationType)); - } - /*! - * Create a new negation expression. - * @param child Expression to be negated. - * @returns Negation expression. - */ - std::shared_ptr<BaseExpression> createNot(std::shared_ptr<BaseExpression> const& child) { - return std::shared_ptr<UnaryBooleanFunctionExpression>(new UnaryBooleanFunctionExpression(child->clone(), UnaryBooleanFunctionExpression::NOT)); - } - /*! - * Create a new And expression. - * @param left Left operand. - * @param right Right operand. - * @returns And expression. - */ - std::shared_ptr<BaseExpression> createAnd(std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) { - return std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(left->clone(), right->clone(), BinaryBooleanFunctionExpression::AND)); - } - /*! - * Create a new Or expression. - * @param left Left operand. - * @param right Right operand. - * @returns Or expression. - */ - std::shared_ptr<BaseExpression> createOr(std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) { - return std::shared_ptr<BinaryBooleanFunctionExpression>(new BinaryBooleanFunctionExpression(left->clone(), right->clone(), BinaryBooleanFunctionExpression::OR)); - } - /*! - * Retrieve boolean variable by name. - * @param name Variable name. - * @returns Boolean variable. - */ - std::shared_ptr<BaseExpression> getBoolVariable(std::string const& name) { - return std::shared_ptr<BaseExpression>(new VariableExpression(*state->getBooleanVariableExpression(name))); - } - /*! - * Retrieve integer variable by name. - * @param name Variable name. - * @returns Integer variable. - */ - std::shared_ptr<BaseExpression> getIntVariable(std::string const& name) { - return std::shared_ptr<BaseExpression>(new VariableExpression(*state->getIntegerVariableExpression(name))); - } - - /*! - * Base method to switch to second run. This does nothing. - * Any subclass that needs to do something in order to proceed to the second run should override this method. - */ - virtual void prepareSecondRun() {} - - protected: - /*! - * Pointer to variable state. - */ - std::shared_ptr<VariableState> state; - - private: - static std::shared_ptr<T> instanceObject; - static bool inSecondRun; - }; - - template <typename T> - std::shared_ptr<T> BaseGrammar<T>::instanceObject; -} -} -} -#endif /* BASEGRAMMAR_H */ - diff --git a/src/parser/prismparser/BooleanExpressionGrammar.cpp b/src/parser/prismparser/BooleanExpressionGrammar.cpp deleted file mode 100644 index a7d9366f8..000000000 --- a/src/parser/prismparser/BooleanExpressionGrammar.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "BooleanExpressionGrammar.h" - -#include "IntegerExpressionGrammar.h" -#include "ConstBooleanExpressionGrammar.h" - -namespace storm { - namespace parser { - namespace prism { - - BooleanExpressionGrammar::BooleanExpressionGrammar(std::shared_ptr<VariableState> const& state) - : BooleanExpressionGrammar::base_type(booleanExpression), BaseGrammar(state) { - - booleanExpression %= orExpression; - booleanExpression.name("boolean expression"); - - orExpression = andExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> andExpression)[qi::_val = phoenix::bind(&BaseGrammar::createOr, this, qi::_val, qi::_1)]; - orExpression.name("boolean expression"); - - andExpression = notExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> notExpression)[qi::_val = phoenix::bind(&BaseGrammar::createAnd, this, qi::_val, qi::_1)]; - andExpression.name("boolean expression"); - - notExpression = atomicBooleanExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicBooleanExpression)[qi::_val = phoenix::bind(&BaseGrammar::createNot, this, qi::_1)]; - notExpression.name("boolean expression"); - - atomicBooleanExpression %= (relativeExpression | booleanVariableExpression | this->state->constantBooleanFormulas_ | this->state->booleanFormulas_ | qi::lit("(") >> booleanExpression >> qi::lit(")") | ConstBooleanExpressionGrammar::instance(this->state)); - atomicBooleanExpression.name("boolean expression"); - - relativeExpression = (IntegerExpressionGrammar::instance(this->state) >> relations_ >> IntegerExpressionGrammar::instance(this->state))[qi::_val = phoenix::bind(&BaseGrammar::createRelation, this, qi::_1, qi::_2, qi::_3)]; - relativeExpression.name("relative expression"); - - booleanVariableExpression = IdentifierGrammar::instance(this->state)[qi::_val = phoenix::bind(&BaseGrammar::getBoolVariable, this, qi::_1)]; - booleanVariableExpression.name("boolean variable"); - } - - void BooleanExpressionGrammar::prepareSecondRun() { - booleanVariableExpression %= this->state->booleanVariables_; - booleanVariableExpression.name("boolean variable"); - } - - } // namespace prism - } // namespace parser -} // namespace storm diff --git a/src/parser/prismparser/BooleanExpressionGrammar.h b/src/parser/prismparser/BooleanExpressionGrammar.h deleted file mode 100644 index 909219fa3..000000000 --- a/src/parser/prismparser/BooleanExpressionGrammar.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * File: BooleanExpressionGrammar.h - * Author: nafur - * - * Created on April 10, 2013, 6:27 PM - */ - -#ifndef BOOLEANEXPRESSIONGRAMMAR_H -#define BOOLEANEXPRESSIONGRAMMAR_H - -#include "Includes.h" -#include "VariableState.h" -#include "IdentifierGrammars.h" -#include "Tokens.h" - -#include <iostream> - -namespace storm { -namespace parser { -namespace prism { - -/*! - * This grammar parses (non constant) boolean expressions as used in prism models. - */ -class BooleanExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<BooleanExpressionGrammar> { -public: - BooleanExpressionGrammar(std::shared_ptr<VariableState> const& state); - /*! - * Switch to second run. - * Variable names may be any valid identifier in the first run, but only defined variables in the second run. - */ - virtual void prepareSecondRun(); - -private: - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> booleanExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> orExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> andExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> notExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> atomicBooleanExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> relativeExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanVariableExpression; - - /*! - * Parser relation operators. - */ - storm::parser::prism::relationalOperatorStruct relations_; -}; - - -} -} -} - -#endif /* BOOLEANEXPRESSIONGRAMMAR_H */ diff --git a/src/parser/prismparser/ConstBooleanExpressionGrammar.cpp b/src/parser/prismparser/ConstBooleanExpressionGrammar.cpp deleted file mode 100644 index a5ce0567d..000000000 --- a/src/parser/prismparser/ConstBooleanExpressionGrammar.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "ConstBooleanExpressionGrammar.h" - -#include "ConstIntegerExpressionGrammar.h" - -namespace storm { -namespace parser { -namespace prism { - - ConstBooleanExpressionGrammar::ConstBooleanExpressionGrammar(std::shared_ptr<VariableState> const& state) - : ConstBooleanExpressionGrammar::base_type(constantBooleanExpression), BaseGrammar(state) { - - constantBooleanExpression %= constantOrExpression; - constantBooleanExpression.name("constant boolean expression"); - - constantOrExpression = constantAndExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> constantAndExpression)[qi::_val = phoenix::bind(&BaseGrammar::createOr, this, qi::_val, qi::_1)]; - constantOrExpression.name("constant boolean expression"); - - constantAndExpression = constantNotExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> constantNotExpression)[qi::_val = phoenix::bind(&BaseGrammar::createAnd, this, qi::_val, qi::_1)]; - constantAndExpression.name("constant boolean expression"); - - constantNotExpression = constantAtomicBooleanExpression[qi::_val = qi::_1] | (qi::lit("!") >> constantAtomicBooleanExpression)[qi::_val = phoenix::bind(&BaseGrammar::createNot, this, qi::_1)]; - constantNotExpression.name("constant boolean expression"); - - constantAtomicBooleanExpression %= (constantRelativeExpression | this->state->constantBooleanFormulas_ | qi::lit("(") >> constantBooleanExpression >> qi::lit(")") | booleanLiteralExpression | booleanConstantExpression); - constantAtomicBooleanExpression.name("constant boolean expression"); - - constantRelativeExpression = (ConstIntegerExpressionGrammar::instance(this->state) >> relations_ >> ConstIntegerExpressionGrammar::instance(this->state))[qi::_val = phoenix::bind(&BaseGrammar::createRelation, this, qi::_1, qi::_2, qi::_3)]; - constantRelativeExpression.name("constant boolean expression"); - - booleanConstantExpression %= (this->state->booleanConstants_ | booleanLiteralExpression); - booleanConstantExpression.name("boolean constant or literal"); - - booleanLiteralExpression = qi::bool_[qi::_val = phoenix::bind(&BaseGrammar::createBoolLiteral, this, qi::_1)]; - booleanLiteralExpression.name("boolean literal"); - } -} -} -} diff --git a/src/parser/prismparser/ConstBooleanExpressionGrammar.h b/src/parser/prismparser/ConstBooleanExpressionGrammar.h deleted file mode 100644 index 8fea3ce95..000000000 --- a/src/parser/prismparser/ConstBooleanExpressionGrammar.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * File: ConstBooleanExpressionGrammar.h - * Author: nafur - * - * Created on April 10, 2013, 6:34 PM - */ - -#ifndef CONSTBOOLEANEXPRESSIONGRAMMAR_H -#define CONSTBOOLEANEXPRESSIONGRAMMAR_H - -#include "Includes.h" -#include "VariableState.h" -#include "IdentifierGrammars.h" -#include "Tokens.h" - -namespace storm { -namespace parser { -namespace prism { - -/*! - * This grammar parses constant boolean expression as used in prism models. - */ -class ConstBooleanExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<ConstBooleanExpressionGrammar> { -public: - ConstBooleanExpressionGrammar(std::shared_ptr<VariableState> const& state); - - -private: - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> constantBooleanExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantOrExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAndExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantNotExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAtomicBooleanExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantRelativeExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanConstantExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanLiteralExpression; - - storm::parser::prism::relationalOperatorStruct relations_; -}; - - -} -} -} - -#endif /* CONSTBOOLEANEXPRESSIONGRAMMAR_H */ - diff --git a/src/parser/prismparser/ConstDoubleExpressionGrammar.cpp b/src/parser/prismparser/ConstDoubleExpressionGrammar.cpp deleted file mode 100644 index 18cd5ae31..000000000 --- a/src/parser/prismparser/ConstDoubleExpressionGrammar.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "ConstDoubleExpressionGrammar.h" - -namespace storm { -namespace parser { -namespace prism { - -ConstDoubleExpressionGrammar::ConstDoubleExpressionGrammar(std::shared_ptr<VariableState> const& state) - : ConstDoubleExpressionGrammar::base_type(constantDoubleExpression), BaseGrammar(state) { - - constantDoubleExpression %= constantDoublePlusExpression; - constantDoubleExpression.name("constant double expression"); - - constantDoublePlusExpression %= constantDoubleMultExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> constantDoubleMultExpression) - [qi::_val = phoenix::bind(&BaseGrammar::createDoublePlus, this, qi::_val, qi::_a, qi::_1)]; - constantDoublePlusExpression.name("constant double expression"); - - constantDoubleMultExpression %= constantAtomicDoubleExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> constantAtomicDoubleExpression) - [qi::_val = phoenix::bind(&BaseGrammar::createDoubleMult, this, qi::_val, qi::_a, qi::_1)]; - constantDoubleMultExpression.name("constant double expression"); - - constantAtomicDoubleExpression %= (qi::lit("(") >> constantDoubleExpression >> qi::lit(")") | this->state->constantDoubleFormulas_ | this->state->constantIntegerFormulas_ | doubleConstantExpression); - constantAtomicDoubleExpression.name("constant double expression"); - - doubleConstantExpression %= (this->state->doubleConstants_ | this->state->integerConstants_ | doubleLiteralExpression); - doubleConstantExpression.name("double constant or literal"); - - doubleLiteralExpression = qi::double_[qi::_val = phoenix::bind(&BaseGrammar::createDoubleLiteral, this, qi::_1)]; - doubleLiteralExpression.name("double literal"); -} - - -} -} -} diff --git a/src/parser/prismparser/ConstDoubleExpressionGrammar.h b/src/parser/prismparser/ConstDoubleExpressionGrammar.h deleted file mode 100644 index 41c503731..000000000 --- a/src/parser/prismparser/ConstDoubleExpressionGrammar.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * File: ConstDoubleExpressionGrammar.h - * Author: nafur - * - * Created on April 10, 2013, 7:04 PM - */ - -#ifndef CONSTDOUBLEEXPRESSIONGRAMMAR_H -#define CONSTDOUBLEEXPRESSIONGRAMMAR_H - -#include "Includes.h" -#include "VariableState.h" -#include "IdentifierGrammars.h" - -namespace storm { - namespace parser { - namespace prism { - - /*! - * This grammar parses constant double expressions as used in prism models. - */ - class ConstDoubleExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<ConstDoubleExpressionGrammar> { - public: - ConstDoubleExpressionGrammar(std::shared_ptr<VariableState> const& state); - - private: - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> constantDoubleExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantDoublePlusExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantDoubleMultExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAtomicDoubleExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> doubleConstantExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> doubleLiteralExpression; - }; - - - } - } -} - -#endif /* CONSTDOUBLEEXPRESSIONGRAMMAR_H */ - diff --git a/src/parser/prismparser/ConstIntegerExpressionGrammar.cpp b/src/parser/prismparser/ConstIntegerExpressionGrammar.cpp deleted file mode 100644 index 9ebebebc7..000000000 --- a/src/parser/prismparser/ConstIntegerExpressionGrammar.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "ConstIntegerExpressionGrammar.h" - -namespace storm { - namespace parser { - namespace prism { - - - ConstIntegerExpressionGrammar::ConstIntegerExpressionGrammar(std::shared_ptr<VariableState> const& state) - : ConstIntegerExpressionGrammar::base_type(constantIntegerExpression), BaseGrammar(state) { - - constantIntegerExpression %= constantIntegerPlusExpression; - constantIntegerExpression.name("constant integer expression"); - - constantIntegerPlusExpression = constantIntegerMultExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> constantIntegerMultExpression) - [qi::_val = phoenix::bind(&BaseGrammar::createIntPlus, this, qi::_val, qi::_a, qi::_1)]; - constantIntegerPlusExpression.name("constant integer expression"); - - constantIntegerMultExpression %= constantAtomicIntegerExpression[qi::_val = qi::_1] >> *(qi::lit("*") >> constantAtomicIntegerExpression) - [qi::_val = phoenix::bind(&BaseGrammar::createIntMult, this, qi::_val, qi::_1)]; - constantIntegerMultExpression.name("constant integer expression"); - - constantAtomicIntegerExpression %= (constantIntegerMinMaxExpression | constantIntegerFloorCeilExpression | this->state->constantIntegerFormulas_ | qi::lit("(") >> constantIntegerExpression >> qi::lit(")") | integerConstantExpression); - constantAtomicIntegerExpression.name("constant integer expression"); - - constantIntegerMinMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> constantIntegerExpression >> qi::lit(",") >> constantIntegerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntMinMax, this, qi::_a, qi::_1, qi::_2)]; - constantIntegerMinMaxExpression.name("integer min/max expression"); - - constantIntegerFloorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> constantIntegerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntFloorCeil, this, qi::_a, qi::_1)]; - constantIntegerFloorCeilExpression.name("integer floor/ceil expression"); - - integerConstantExpression %= (this->state->integerConstants_ | integerLiteralExpression); - integerConstantExpression.name("integer constant or literal"); - - integerLiteralExpression = qi::int_[qi::_val = phoenix::bind(&BaseGrammar::createIntLiteral, this, qi::_1)]; - integerLiteralExpression.name("integer literal"); - - } - - } // namespace prism - } // namespace parser -} // namespace storm diff --git a/src/parser/prismparser/ConstIntegerExpressionGrammar.h b/src/parser/prismparser/ConstIntegerExpressionGrammar.h deleted file mode 100644 index 2b6a08cae..000000000 --- a/src/parser/prismparser/ConstIntegerExpressionGrammar.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * File: ConstIntegerExpressionGrammar.h - * Author: nafur - * - * Created on April 10, 2013, 6:02 PM - */ - -#ifndef CONSTINTEGEREXPRESSIONGRAMMAR_H -#define CONSTINTEGEREXPRESSIONGRAMMAR_H - -#include "Includes.h" -#include "VariableState.h" -#include "IdentifierGrammars.h" - -namespace storm { - namespace parser { - namespace prism { - - /*! - * This grammar parses constant integer expressions as used in prism models. - */ - class ConstIntegerExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<ConstIntegerExpressionGrammar> { - public: - ConstIntegerExpressionGrammar(std::shared_ptr<VariableState> const& state); - - private: - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> constantIntegerExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantIntegerPlusExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantIntegerMultExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAtomicIntegerExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerConstantExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerLiteralExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantIntegerMinMaxExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantIntegerFloorCeilExpression; - }; - - - } - } -} - -#endif /* CONSTINTEGEREXPRESSIONGRAMMAR_H */ diff --git a/src/parser/prismparser/IdentifierGrammars.cpp b/src/parser/prismparser/IdentifierGrammars.cpp deleted file mode 100644 index ec6f14931..000000000 --- a/src/parser/prismparser/IdentifierGrammars.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "IdentifierGrammars.h" - -namespace storm { - namespace parser { - namespace prism { - - IdentifierGrammar::IdentifierGrammar(std::shared_ptr<VariableState> const& state) - : IdentifierGrammar::base_type(identifierName), BaseGrammar(state) { - - identifierName %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][ qi::_pass = phoenix::bind(&VariableState::isIdentifier, this->state.get(), qi::_1) ]; - identifierName.name("identifier"); - } - - FreeIdentifierGrammar::FreeIdentifierGrammar(std::shared_ptr<VariableState> const& state) - : FreeIdentifierGrammar::base_type(freeIdentifierName), BaseGrammar(state) { - - freeIdentifierName %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][ qi::_pass = phoenix::bind(&VariableState::isFreeIdentifier, this->state.get(), qi::_1) ]; - freeIdentifierName.name("identifier"); - } - - } - } -} \ No newline at end of file diff --git a/src/parser/prismparser/IdentifierGrammars.h b/src/parser/prismparser/IdentifierGrammars.h deleted file mode 100644 index ccb14bbc1..000000000 --- a/src/parser/prismparser/IdentifierGrammars.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * File: Keywords.h - * Author: nafur - * - * Created on April 10, 2013, 6:03 PM - */ - -#ifndef IDENTIFIERGRAMMARS_H -#define IDENTIFIERGRAMMARS_H - -#include "Includes.h" -#include "BaseGrammar.h" -#include "VariableState.h" - -namespace storm { - namespace parser { - namespace prism { - - /*! - * This grammar parses a (possibly used) identifier as used in a prism models. - */ - class IdentifierGrammar : public qi::grammar<Iterator, std::string(), Skipper, Unused>, public BaseGrammar<IdentifierGrammar> { - public: - IdentifierGrammar(std::shared_ptr<VariableState> const& state); - private: - qi::rule<Iterator, std::string(), Skipper> identifierName; - }; - - /*! - * This grammar parses an used identifier as used in a prism models. - */ - class FreeIdentifierGrammar : public qi::grammar<Iterator, std::string(), Skipper, Unused>, public BaseGrammar<IdentifierGrammar> { - public: - FreeIdentifierGrammar(std::shared_ptr<VariableState> const& state); - private: - qi::rule<Iterator, std::string(), Skipper> freeIdentifierName; - }; - } - } -} -#endif /* IDENTIFIERGRAMMARS_H */ - diff --git a/src/parser/prismparser/Includes.h b/src/parser/prismparser/Includes.h deleted file mode 100644 index 49a720dad..000000000 --- a/src/parser/prismparser/Includes.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * File: Includes - * Author: Gereon Kremer - * - * Created on April 10, 2013, 4:46 PM - */ - -#ifndef BOOSTINCLUDES_H -#define BOOSTINCLUDES_H - -// Used for Boost spirit. -#include <boost/typeof/typeof.hpp> -#include <boost/spirit/include/qi.hpp> -#include <boost/spirit/include/phoenix.hpp> - -// Include headers for spirit iterators. Needed for diagnostics and input stream iteration. -#include <boost/spirit/include/classic_position_iterator.hpp> -#include <boost/spirit/include/support_multi_pass.hpp> - -namespace qi = boost::spirit::qi; -namespace phoenix = boost::phoenix; - -typedef std::string::const_iterator BaseIteratorType; -typedef boost::spirit::classic::position_iterator2<BaseIteratorType> PositionIteratorType; -typedef PositionIteratorType Iterator; -typedef BOOST_TYPEOF(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol) Skipper; -typedef BOOST_TYPEOF(qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol | boost::spirit::ascii::space) Skipper2; -typedef boost::spirit::unused_type Unused; - -#include "src/ir/IR.h" -using namespace storm::ir; -using namespace storm::ir::expressions; - -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" -extern log4cplus::Logger logger; - -#endif /* BOOSTINCLUDES_H */ - diff --git a/src/parser/prismparser/IntegerExpressionGrammar.cpp b/src/parser/prismparser/IntegerExpressionGrammar.cpp deleted file mode 100644 index 3bcfd4d4f..000000000 --- a/src/parser/prismparser/IntegerExpressionGrammar.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "IntegerExpressionGrammar.h" - -#include "IdentifierGrammars.h" -#include "ConstIntegerExpressionGrammar.h" - -namespace storm { - namespace parser { - namespace prism { - - IntegerExpressionGrammar::IntegerExpressionGrammar(std::shared_ptr<VariableState> const& state) - : IntegerExpressionGrammar::base_type(integerExpression), BaseGrammar(state) { - - integerExpression %= integerPlusExpression; - integerExpression.name("integer expression"); - - integerPlusExpression = integerMultExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> integerMultExpression)[qi::_val = phoenix::bind(&BaseGrammar::createIntPlus, this, qi::_val, qi::_a, qi::_1)]; - integerPlusExpression.name("integer expression"); - - integerMultExpression %= atomicIntegerExpression[qi::_val = qi::_1] >> *(qi::lit("*") >> atomicIntegerExpression[qi::_val = phoenix::bind(&BaseGrammar::createIntMult, this, qi::_val, qi::_1)]); - integerMultExpression.name("integer expression"); - - atomicIntegerExpression %= (integerMinMaxExpression | integerFloorCeilExpression | this->state->constantIntegerFormulas_ | this->state->integerFormulas_ | qi::lit("(") >> integerExpression >> qi::lit(")") | integerVariableExpression | ConstIntegerExpressionGrammar::instance(this->state)); - atomicIntegerExpression.name("integer expression"); - - integerMinMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> integerExpression >> qi::lit(",") >> integerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntMinMax, this, qi::_a, qi::_1, qi::_2)]; - integerMinMaxExpression.name("integer min/max expression"); - - integerFloorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> integerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntFloorCeil, this, qi::_a, qi::_1)]; - integerFloorCeilExpression.name("integer floor/ceil expression"); - - integerVariableExpression = IdentifierGrammar::instance(this->state)[qi::_val = phoenix::bind(&BaseGrammar::getIntVariable, this, qi::_1)]; - integerVariableExpression.name("integer variable"); - } - - void IntegerExpressionGrammar::prepareSecondRun() { - integerVariableExpression %= this->state->integerVariables_; - integerVariableExpression.name("integer variable"); - } - - } - } -} diff --git a/src/parser/prismparser/IntegerExpressionGrammar.h b/src/parser/prismparser/IntegerExpressionGrammar.h deleted file mode 100644 index 7531ef36e..000000000 --- a/src/parser/prismparser/IntegerExpressionGrammar.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * File: IntegerExpressionGrammar.h - * Author: nafur - * - * Created on April 10, 2013, 4:39 PM - */ - -#ifndef INTEGEREXPRESSIONGRAMMAR_H -#define INTEGEREXPRESSIONGRAMMAR_H - -#include "src/ir/IR.h" -#include "VariableState.h" -#include "Includes.h" -#include "IdentifierGrammars.h" - -#include <memory> - -namespace storm { - namespace parser { - namespace prism { - - /*! - * This grammar parses a (non constant) integer expressions as used in prism models. - */ - class IntegerExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<IntegerExpressionGrammar> { - public: - IntegerExpressionGrammar(std::shared_ptr<VariableState> const& state); - - /*! - * Switch to second run. - * Variable names may be any valid identifier in the first run, but only defined variables in the second run. - */ - virtual void prepareSecondRun(); - - private: - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> integerExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> integerPlusExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerMultExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> atomicIntegerExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerVariableExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> integerMinMaxExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> integerFloorCeilExpression; - }; - - } - } -} - -#endif /* INTEGEREXPRESSIONGRAMMAR_H */ - diff --git a/src/parser/prismparser/PrismGrammar.cpp b/src/parser/prismparser/PrismGrammar.cpp deleted file mode 100644 index b6de4f0f4..000000000 --- a/src/parser/prismparser/PrismGrammar.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * PrismGrammar.cpp - * - * Created on: 11.01.2013 - * Author: chris - */ - -// Needed for file IO. -#include <fstream> -#include <iomanip> -#include <limits> - -#include "PrismGrammar.h" - -#include "src/utility/OsDetection.h" - -#include "src/parser/prismparser/Includes.h" -#include "src/parser/prismparser/BooleanExpressionGrammar.h" -#include "src/parser/prismparser/ConstBooleanExpressionGrammar.h" -#include "src/parser/prismparser/ConstDoubleExpressionGrammar.h" -#include "src/parser/prismparser/ConstIntegerExpressionGrammar.h" -#include "src/parser/prismparser/IntegerExpressionGrammar.h" -#include "src/parser/prismparser/IdentifierGrammars.h" -#include "src/parser/prismparser/VariableState.h" -#include "src/exceptions/InvalidArgumentException.h" - -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" -extern log4cplus::Logger logger; - -// Some typedefs and namespace definitions to reduce code size. -typedef std::string::const_iterator BaseIteratorType; -typedef boost::spirit::classic::position_iterator2<BaseIteratorType> PositionIteratorType; -namespace qi = boost::spirit::qi; -namespace phoenix = boost::phoenix; - -namespace storm { - namespace parser { - namespace prism { - - void PrismGrammar::addLabel(std::string const& name, std::shared_ptr<BaseExpression> const& value, std::map<std::string, std::unique_ptr<BaseExpression>>& nameToExpressionMap) { - this->state->labelNames_.add(name, name); - nameToExpressionMap[name] = value->clone(); - } - - void PrismGrammar::addIntegerAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& value, std::map<std::string, Assignment>& variableToAssignmentMap) { - this->state->assignedIntegerVariables_.add(variable, variable); - variableToAssignmentMap[variable] = Assignment(variable, value->clone()); - } - - void PrismGrammar::addBooleanAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& value, std::map<std::string, Assignment>& variableToAssigmentMap) { - this->state->assignedBooleanVariables_.add(variable, variable); - variableToAssigmentMap[variable] = Assignment(variable, value->clone()); - } - - void PrismGrammar::addUndefinedBooleanConstant(std::string const& name, std::map<std::string, std::unique_ptr<BooleanConstantExpression>>& nameToExpressionMap) { - this->state->booleanConstants_.add(name, std::shared_ptr<BaseExpression>(new BooleanConstantExpression(name))); - this->state->allConstantNames_.add(name, name); - nameToExpressionMap.emplace(name, std::unique_ptr<BooleanConstantExpression>(new BooleanConstantExpression(dynamic_cast<BooleanConstantExpression&>(*this->state->booleanConstants_.at(name))))); - } - - void PrismGrammar::addUndefinedIntegerConstant(std::string const& name, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>& nameToExpressionMap) { - this->state->integerConstants_.add(name, std::shared_ptr<BaseExpression>(new IntegerConstantExpression(name))); - this->state->allConstantNames_.add(name, name); - nameToExpressionMap.emplace(name, std::unique_ptr<IntegerConstantExpression>(new IntegerConstantExpression(dynamic_cast<IntegerConstantExpression&>(*this->state->integerConstants_.at(name))))); - } - - void PrismGrammar::addUndefinedDoubleConstant(std::string const& name, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>& nameToExpressionMap) { - this->state->doubleConstants_.add(name, std::shared_ptr<BaseExpression>(new DoubleConstantExpression(name))); - this->state->allConstantNames_.add(name, name); - nameToExpressionMap.emplace(name, std::unique_ptr<DoubleConstantExpression>(new DoubleConstantExpression(dynamic_cast<DoubleConstantExpression&>(*this->state->doubleConstants_.at(name))))); - } - - Module PrismGrammar::renameModule(std::string const& newName, std::string const& oldName, std::map<std::string, std::string> const& renaming) { - this->state->moduleNames_.add(newName, newName); - Module* old = this->moduleMap_.find(oldName); - if (old == nullptr) { - LOG4CPLUS_ERROR(logger, "Renaming module failed: module " << oldName << " does not exist."); - throw storm::exceptions::InvalidArgumentException() << "Renaming module failed: module " << oldName << " does not exist."; - } - Module res(*old, newName, renaming, *this->state); - this->moduleMap_.at(newName) = res; - return res; - } - - Module PrismGrammar::createModule(std::string const& name, std::vector<BooleanVariable> const& bools, std::vector<IntegerVariable> const& ints, std::map<std::string, uint_fast64_t> const& boolids, std::map<std::string, uint_fast64_t> const& intids, std::vector<storm::ir::Command> const& commands) { - this->state->moduleNames_.add(name, name); - Module res(name, bools, ints, boolids, intids, commands); - this->moduleMap_.at(name) = res; - return res; - } - - void PrismGrammar::createIntegerVariable(std::string const& name, std::shared_ptr<BaseExpression> const& lower, std::shared_ptr<BaseExpression> const& upper, std::shared_ptr<BaseExpression> const& init, std::vector<IntegerVariable>& vars, std::map<std::string, uint_fast64_t>& varids, bool isGlobalVariable) { - uint_fast64_t id = this->state->addIntegerVariable(name); - uint_fast64_t newLocalIndex = this->state->nextLocalIntegerVariableIndex; - vars.emplace_back(newLocalIndex, id, name, lower != nullptr ? lower->clone() : nullptr, upper != nullptr ? upper->clone() : nullptr, init != nullptr ? init->clone() : nullptr); - varids[name] = newLocalIndex; - ++this->state->nextLocalIntegerVariableIndex; - this->state->localIntegerVariables_.add(name, name); - if (isGlobalVariable) { - this->state->globalIntegerVariables_.add(name, name); - } - } - - void PrismGrammar::createBooleanVariable(std::string const& name, std::shared_ptr<BaseExpression> const& init, std::vector<BooleanVariable>& vars, std::map<std::string, uint_fast64_t>& varids, bool isGlobalVariable) { - uint_fast64_t id = this->state->addBooleanVariable(name); - uint_fast64_t newLocalIndex = this->state->nextLocalBooleanVariableIndex; - vars.emplace_back(newLocalIndex, id, name, init != nullptr ? init->clone() : nullptr); - varids[name] = newLocalIndex; - ++this->state->nextLocalBooleanVariableIndex; - this->state->localBooleanVariables_.add(name, name); - if (isGlobalVariable) { - this->state->globalBooleanVariables_.add(name, name); - } - } - - StateReward createStateReward(std::shared_ptr<BaseExpression> const& guard, std::shared_ptr<BaseExpression> const& reward) { - return StateReward(guard->clone(), reward->clone()); - } - TransitionReward createTransitionReward(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::shared_ptr<BaseExpression> const& reward) { - return TransitionReward(label, guard->clone(), reward->clone()); - } - void createRewardModel(std::string const& name, std::vector<StateReward>& stateRewards, std::vector<TransitionReward>& transitionRewards, std::map<std::string, RewardModel>& mapping) { - mapping[name] = RewardModel(name, stateRewards, transitionRewards); - } - Update PrismGrammar::createUpdate(std::shared_ptr<BaseExpression> const& likelihood, std::map<std::string, Assignment> const& bools, std::map<std::string, Assignment> const& ints) { - this->state->nextGlobalUpdateIndex++; - return Update(this->state->getNextGlobalUpdateIndex() - 1, likelihood != nullptr ? likelihood->clone() : nullptr, bools, ints); - } - Command PrismGrammar::createCommand(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::vector<Update> const& updates) { - this->state->nextGlobalCommandIndex++; - return Command(this->state->getNextGlobalCommandIndex() - 1, label, guard->clone(), updates); - } - Program createProgram( - Program::ModelType modelType, - std::map<std::string, std::unique_ptr<BooleanConstantExpression>> const& undefBoolConst, - std::map<std::string, std::unique_ptr<IntegerConstantExpression>> const& undefIntConst, - std::map<std::string, std::unique_ptr<DoubleConstantExpression>> const& undefDoubleConst, - GlobalVariableInformation const& globalVariableInformation, - std::vector<Module> const& modules, - std::map<std::string, RewardModel> const& rewards, - std::map<std::string, std::unique_ptr<BaseExpression>> const& labels) { - return Program(modelType, undefBoolConst, undefIntConst, undefDoubleConst, - globalVariableInformation.booleanVariables, globalVariableInformation.integerVariables, - globalVariableInformation.booleanVariableToIndexMap, - globalVariableInformation.integerVariableToIndexMap, modules, rewards, labels); - } - - PrismGrammar::PrismGrammar() : PrismGrammar::base_type(start), state(new VariableState()) { - - labelDefinition = (qi::lit("label") >> -qi::lit("\"") >> FreeIdentifierGrammar::instance(this->state) >> -qi::lit("\"") >> qi::lit("=") >> BooleanExpressionGrammar::instance(this->state) >> qi::lit(";")) - [phoenix::bind(&PrismGrammar::addLabel, this, qi::_1, qi::_2, qi::_r1)]; - labelDefinition.name("label declaration"); - labelDefinitionList %= *labelDefinition(qi::_r1); - labelDefinitionList.name("label declaration list"); - - // This block defines all entities that are needed for parsing a reward model. - stateRewardDefinition = (BooleanExpressionGrammar::instance(this->state) > qi::lit(":") > ConstDoubleExpressionGrammar::instance(this->state) >> qi::lit(";"))[qi::_val = phoenix::bind(&createStateReward, qi::_1, qi::_2)]; - stateRewardDefinition.name("state reward definition"); - transitionRewardDefinition = (qi::lit("[") > -(commandName[qi::_a = qi::_1]) > qi::lit("]") > BooleanExpressionGrammar::instance(this->state) > qi::lit(":") > ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(";"))[qi::_val = phoenix::bind(&createTransitionReward, qi::_a, qi::_2, qi::_3)]; - transitionRewardDefinition.name("transition reward definition"); - rewardDefinition = (qi::lit("rewards") > qi::lit("\"") > FreeIdentifierGrammar::instance(this->state) > qi::lit("\"") > +(stateRewardDefinition[phoenix::push_back(qi::_a, qi::_1)] | transitionRewardDefinition[phoenix::push_back(qi::_b, qi::_1)]) >> qi::lit("endrewards")) - [phoenix::bind(&createRewardModel, qi::_1, qi::_a, qi::_b, qi::_r1)]; - rewardDefinition.name("reward definition"); - rewardDefinitionList = *rewardDefinition(qi::_r1); - rewardDefinitionList.name("reward definition list"); - - commandName %= this->state->commandNames_; - commandName.name("command name"); - unassignedLocalBooleanVariableName %= (this->state->localBooleanVariables_ | this->state->globalBooleanVariables_) - this->state->assignedBooleanVariables_; - unassignedLocalBooleanVariableName.name("unassigned local/global boolean variable"); - unassignedLocalIntegerVariableName %= (this->state->localIntegerVariables_ | this->state->globalIntegerVariables_) - this->state->assignedIntegerVariables_; - unassignedLocalIntegerVariableName.name("unassigned local/global integer variable"); - - // This block defines all entities that are needed for parsing a single command. - assignmentDefinition = - (qi::lit("(") >> unassignedLocalIntegerVariableName > qi::lit("'") > qi::lit("=") > IntegerExpressionGrammar::instance(this->state) > qi::lit(")"))[phoenix::bind(&PrismGrammar::addIntegerAssignment, this, qi::_1, qi::_2, qi::_r2)] | - (qi::lit("(") >> unassignedLocalBooleanVariableName > qi::lit("'") > qi::lit("=") > BooleanExpressionGrammar::instance(this->state) > qi::lit(")"))[phoenix::bind(&PrismGrammar::addBooleanAssignment, this, qi::_1, qi::_2, qi::_r1)]; - assignmentDefinition.name("assignment"); - assignmentDefinitionList = assignmentDefinition(qi::_r1, qi::_r2) % "&"; - assignmentDefinitionList.name("assignment list"); - updateDefinition = (((ConstDoubleExpressionGrammar::instance(this->state) >> qi::lit(":")) - | qi::attr(std::shared_ptr<BaseExpression>(new storm::ir::expressions::DoubleLiteralExpression(1))))[phoenix::clear(phoenix::ref(this->state->assignedBooleanVariables_)), phoenix::clear(phoenix::ref(this->state->assignedIntegerVariables_))] - >> assignmentDefinitionList(qi::_a, qi::_b))[qi::_val = phoenix::bind(&PrismGrammar::createUpdate, this, qi::_1, qi::_a, qi::_b)]; - updateDefinition.name("update"); - updateListDefinition = +updateDefinition % "+"; - updateListDefinition.name("update list"); - commandDefinition = ( - qi::lit("[") > -( - (FreeIdentifierGrammar::instance(this->state)[phoenix::bind(this->state->commandNames_.add, qi::_1, qi::_1)] | commandName)[qi::_a = qi::_1] - ) > qi::lit("]") > BooleanExpressionGrammar::instance(this->state) > qi::lit("->") > updateListDefinition > qi::lit(";") - )[qi::_val = phoenix::bind(&PrismGrammar::createCommand, this, qi::_a, qi::_2, qi::_3)]; - commandDefinition.name("command"); - - // This block defines all entities that are needed for parsing variable definitions. - booleanVariableDefinition = (FreeIdentifierGrammar::instance(this->state) >> qi::lit(":") >> qi::lit("bool") > -(qi::lit("init") > ConstBooleanExpressionGrammar::instance(this->state)[qi::_b = phoenix::construct<std::shared_ptr<BaseExpression>>(qi::_1)]) > qi::lit(";")) - [phoenix::bind(&PrismGrammar::createBooleanVariable, this, qi::_1, qi::_b, qi::_r1, qi::_r2, qi::_r3)]; - booleanVariableDefinition.name("boolean variable declaration"); - - integerVariableDefinition = (FreeIdentifierGrammar::instance(this->state) >> qi::lit(":") >> qi::lit("[") > ConstIntegerExpressionGrammar::instance(this->state) > qi::lit("..") > ConstIntegerExpressionGrammar::instance(this->state) > qi::lit("]") > -(qi::lit("init") > ConstIntegerExpressionGrammar::instance(this->state)[qi::_b = phoenix::construct<std::shared_ptr<BaseExpression>>(qi::_1)]) > qi::lit(";")) - [phoenix::bind(&PrismGrammar::createIntegerVariable, this, qi::_1, qi::_2, qi::_3, qi::_b, qi::_r1, qi::_r2, qi::_r3)]; - integerVariableDefinition.name("integer variable declaration"); - variableDefinition = (booleanVariableDefinition(qi::_r1, qi::_r3, false) | integerVariableDefinition(qi::_r2, qi::_r4, false)); - variableDefinition.name("variable declaration"); - - // This block defines all entities that are needed for parsing a module. - moduleDefinition = (qi::lit("module") >> FreeIdentifierGrammar::instance(this->state)[phoenix::bind(&VariableState::clearLocalVariables, *this->state)] - >> *(variableDefinition(qi::_a, qi::_b, qi::_c, qi::_d)) >> +commandDefinition > qi::lit("endmodule")) - [qi::_val = phoenix::bind(&PrismGrammar::createModule, this, qi::_1, qi::_a, qi::_b, qi::_c, qi::_d, qi::_2)]; - - moduleDefinition.name("module"); - moduleRenaming = (qi::lit("module") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") - > this->state->moduleNames_ > qi::lit("[") > *( - (IdentifierGrammar::instance(this->state) > qi::lit("=") > IdentifierGrammar::instance(this->state) >> -qi::lit(","))[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string,std::string>>(qi::_1, qi::_2))] - ) > qi::lit("]") > qi::lit("endmodule")) - [qi::_val = phoenix::bind(&PrismGrammar::renameModule, this, qi::_1, qi::_2, qi::_a)]; - moduleRenaming.name("renamed module"); - moduleDefinitionList %= +(moduleDefinition | moduleRenaming); - moduleDefinitionList.name("module list"); - - // This block defines all entities that are needed for parsing global variable definitions. - globalVariableDefinitionList = *(qi::lit("global") > (booleanVariableDefinition(bind(&GlobalVariableInformation::booleanVariables, qi::_r1), bind(&GlobalVariableInformation::booleanVariableToIndexMap, qi::_r1), true) | integerVariableDefinition(bind(&GlobalVariableInformation::integerVariables, qi::_r1), bind(&GlobalVariableInformation::integerVariableToIndexMap, qi::_r1), true))); - globalVariableDefinitionList.name("global variable declaration list"); - - // This block defines all entities that are needed for parsing constant definitions. - definedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") > ConstBooleanExpressionGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(this->state->booleanConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2]; - definedBooleanConstantDefinition.name("defined boolean constant declaration"); - definedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstIntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->integerConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2]; - definedIntegerConstantDefinition.name("defined integer constant declaration"); - definedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") > ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(this->state->doubleConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2]; - definedDoubleConstantDefinition.name("defined double constant declaration"); - undefinedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedBooleanConstant, this, qi::_1, qi::_r1)]; - undefinedBooleanConstantDefinition.name("undefined boolean constant declaration"); - undefinedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedIntegerConstant, this, qi::_1, qi::_r1)]; - undefinedIntegerConstantDefinition.name("undefined integer constant declaration"); - undefinedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedDoubleConstant, this, qi::_1, qi::_r1)]; - undefinedDoubleConstantDefinition.name("undefined double constant declaration"); - definedConstantDefinition %= (definedBooleanConstantDefinition | definedIntegerConstantDefinition | definedDoubleConstantDefinition); - definedConstantDefinition.name("defined constant declaration"); - undefinedConstantDefinition = (undefinedBooleanConstantDefinition(qi::_r1) | undefinedIntegerConstantDefinition(qi::_r2) | undefinedDoubleConstantDefinition(qi::_r3)); - undefinedConstantDefinition.name("undefined constant declaration"); - constantDefinitionList = *(definedConstantDefinition | undefinedConstantDefinition(qi::_r1, qi::_r2, qi::_r3)); - constantDefinitionList.name("constant declaration list"); - - constantBooleanFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstBooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->constantBooleanFormulas_.add, qi::_1, qi::_2)]; - constantBooleanFormulaDefinition.name("constant boolean formula definition"); - booleanFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> BooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->booleanFormulas_.add, qi::_1, qi::_2)]; - booleanFormulaDefinition.name("boolean formula definition"); - constantIntegerFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstIntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->constantIntegerFormulas_.add, qi::_1, qi::_2)]; - constantIntegerFormulaDefinition.name("constant integer formula definition"); - integerFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> IntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->integerFormulas_.add, qi::_1, qi::_2)]; - integerFormulaDefinition.name("integer formula definition"); - constantDoubleFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstDoubleExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->constantDoubleFormulas_.add, qi::_1, qi::_2)]; - constantDoubleFormulaDefinition.name("constant double formula definition"); - formulaDefinition = constantBooleanFormulaDefinition | booleanFormulaDefinition | constantIntegerFormulaDefinition | integerFormulaDefinition | constantDoubleFormulaDefinition; - formulaDefinition.name("formula definition"); - formulaDefinitionList = *formulaDefinition; - formulaDefinitionList.name("formula definition list"); - - // This block defines all entities that are needed for parsing a program. - modelTypeDefinition = modelType_; - modelTypeDefinition.name("model type"); - start = (qi::eps > - modelTypeDefinition > - constantDefinitionList(qi::_a, qi::_b, qi::_c) > - formulaDefinitionList > - globalVariableDefinitionList(qi::_d) > - moduleDefinitionList > - rewardDefinitionList(qi::_e) > - labelDefinitionList(qi::_f))[qi::_val = phoenix::bind(&createProgram, qi::_1, qi::_a, qi::_b, qi::_c, qi::_d, qi::_2, qi::_e, qi::_f)]; - start.name("probabilistic program declaration"); - } - - void PrismGrammar::prepareForSecondRun() { - LOG4CPLUS_INFO(logger, "Preparing parser for second run."); - this->state->prepareForSecondRun(); - BooleanExpressionGrammar::secondRun(); - ConstBooleanExpressionGrammar::secondRun(); - ConstDoubleExpressionGrammar::secondRun(); - ConstIntegerExpressionGrammar::secondRun(); - IntegerExpressionGrammar::secondRun(); - } - - void PrismGrammar::resetGrammars() { - LOG4CPLUS_INFO(logger, "Resetting grammars."); - BooleanExpressionGrammar::resetInstance(); - ConstBooleanExpressionGrammar::resetInstance(); - ConstDoubleExpressionGrammar::resetInstance(); - ConstIntegerExpressionGrammar::resetInstance(); - IntegerExpressionGrammar::resetInstance(); - } - - } // namespace prism - } // namespace parser -} // namespace storm diff --git a/src/parser/prismparser/PrismGrammar.h b/src/parser/prismparser/PrismGrammar.h deleted file mode 100644 index 57ba55c5b..000000000 --- a/src/parser/prismparser/PrismGrammar.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * File: PrismGrammar.h - * Author: nafur - * - * Created on April 30, 2013, 5:20 PM - */ - -#ifndef STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H -#define STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H - -// All classes of the intermediate representation are used. -#include "src/ir/IR.h" -#include "src/parser/prismparser/Includes.h" -#include "src/parser/prismparser/Tokens.h" -#include "src/parser/prismparser/IdentifierGrammars.h" -#include "src/parser/prismparser/VariableState.h" -#include "src/parser/prismparser/ConstBooleanExpressionGrammar.h" -#include "src/parser/prismparser/ConstDoubleExpressionGrammar.h" -#include "src/parser/prismparser/ConstIntegerExpressionGrammar.h" -#include "src/parser/prismparser/BooleanExpressionGrammar.h" -#include "src/parser/prismparser/IntegerExpressionGrammar.h" - -// Used for file input. -#include <istream> -#include <memory> - -namespace storm { - namespace parser { - namespace prism { - - using namespace storm::ir; - using namespace storm::ir::expressions; - - struct GlobalVariableInformation { - std::vector<BooleanVariable> booleanVariables; - std::vector<IntegerVariable> integerVariables; - std::map<std::string, uint_fast64_t> booleanVariableToIndexMap; - std::map<std::string, uint_fast64_t> integerVariableToIndexMap; - }; - - /*! - * The Boost spirit grammar for the PRISM language. Returns the intermediate representation of - * the input that complies with the PRISM syntax. - */ - class PrismGrammar : public qi::grammar< - Iterator, - Program(), - qi::locals< - std::map<std::string, std::unique_ptr<BooleanConstantExpression>>, - std::map<std::string, std::unique_ptr<IntegerConstantExpression>>, - std::map<std::string, std::unique_ptr<DoubleConstantExpression>>, - GlobalVariableInformation, - std::map<std::string, RewardModel>, - std::map<std::string, std::unique_ptr<BaseExpression>> - >, - Skipper> { - public: - /*! - * Default constructor that creates an empty and functional grammar. - */ - PrismGrammar(); - - /*! - * Puts all sub-grammars into the mode for performing the second run. A two-run model was chosen - * because modules can involve variables that are only declared afterwards, so the first run - * creates all variables and the second one tries to parse the full model. - */ - void prepareForSecondRun(); - - /*! - * Resets all sub-grammars, i.e. puts them into an initial state. - */ - void resetGrammars(); - - private: - - std::shared_ptr<storm::parser::prism::VariableState> state; - struct qi::symbols<char, Module> moduleMap_; - - // The starting point of the grammar. - qi::rule< - Iterator, - Program(), - qi::locals< - std::map<std::string, std::unique_ptr<BooleanConstantExpression>>, - std::map<std::string, std::unique_ptr<IntegerConstantExpression>>, - std::map<std::string, std::unique_ptr<DoubleConstantExpression>>, - GlobalVariableInformation, - std::map<std::string, RewardModel>, - std::map<std::string, std::unique_ptr<BaseExpression>> - >, - Skipper> start; - qi::rule<Iterator, Program::ModelType(), Skipper> modelTypeDefinition; - qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> constantDefinitionList; - qi::rule<Iterator, std::vector<Module>(), Skipper> moduleDefinitionList; - - // Rules for global variable definitions - qi::rule<Iterator, qi::unused_type(GlobalVariableInformation&), Skipper> globalVariableDefinitionList; - - // Rules for module definition. - qi::rule<Iterator, Module(), qi::locals<std::vector<BooleanVariable>, std::vector<IntegerVariable>, std::map<std::string, uint_fast64_t>, std::map<std::string, uint_fast64_t>>, Skipper> moduleDefinition; - qi::rule<Iterator, Module(), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming; - - // Rules for variable definitions. - qi::rule<Iterator, qi::unused_type(std::vector<BooleanVariable>&, std::vector<IntegerVariable>&, std::map<std::string, uint_fast64_t>&, std::map<std::string, uint_fast64_t>&), Skipper> variableDefinition; - qi::rule<Iterator, qi::unused_type(std::vector<BooleanVariable>&, std::map<std::string, uint_fast64_t>&, bool), qi::locals<uint_fast64_t, std::shared_ptr<BaseExpression>>, Skipper> booleanVariableDefinition; - qi::rule<Iterator, qi::unused_type(std::vector<IntegerVariable>&, std::map<std::string, uint_fast64_t>&, bool), qi::locals<uint_fast64_t, std::shared_ptr<BaseExpression>>, Skipper> integerVariableDefinition; - - // Rules for command definitions. - qi::rule<Iterator, Command(), qi::locals<std::string>, Skipper> commandDefinition; - qi::rule<Iterator, std::vector<Update>(), Skipper> updateListDefinition; - qi::rule<Iterator, Update(), qi::locals<std::map<std::string, Assignment>, std::map<std::string, Assignment>>, Skipper> updateDefinition; - qi::rule<Iterator, qi::unused_type(std::map<std::string, Assignment>&, std::map<std::string, Assignment>&), Skipper> assignmentDefinitionList; - qi::rule<Iterator, qi::unused_type(std::map<std::string, Assignment>&, std::map<std::string, Assignment>&), Skipper> assignmentDefinition; - - // Rules for variable/command names. - qi::rule<Iterator, std::string(), Skipper> commandName; - qi::rule<Iterator, std::string(), Skipper> unassignedLocalBooleanVariableName; - qi::rule<Iterator, std::string(), Skipper> unassignedLocalIntegerVariableName; - - // Rules for reward definitions. - qi::rule<Iterator, qi::unused_type(std::map<std::string, RewardModel>&), Skipper> rewardDefinitionList; - qi::rule<Iterator, qi::unused_type(std::map<std::string, RewardModel>&), qi::locals<std::vector<StateReward>, std::vector<TransitionReward>>, Skipper> rewardDefinition; - qi::rule<Iterator, StateReward(), Skipper> stateRewardDefinition; - qi::rule<Iterator, TransitionReward(), qi::locals<std::string>, Skipper> transitionRewardDefinition; - - // Rules for label definitions. - qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BaseExpression>>&), Skipper> labelDefinitionList; - qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BaseExpression>>&), Skipper> labelDefinition; - - // Rules for constant definitions. - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantDefinition; - qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> undefinedConstantDefinition; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedConstantDefinition; - qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&), Skipper> undefinedBooleanConstantDefinition; - qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&), Skipper> undefinedIntegerConstantDefinition; - qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> undefinedDoubleConstantDefinition; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedBooleanConstantDefinition; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedIntegerConstantDefinition; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedDoubleConstantDefinition; - - // Rules for formula definitions. - qi::rule<Iterator, qi::unused_type(), Skipper> formulaDefinitionList; - qi::rule<Iterator, qi::unused_type(), Skipper> formulaDefinition; - qi::rule<Iterator, qi::unused_type(), Skipper> constantIntegerFormulaDefinition; - qi::rule<Iterator, qi::unused_type(), Skipper> integerFormulaDefinition; - qi::rule<Iterator, qi::unused_type(), Skipper> constantDoubleFormulaDefinition; - qi::rule<Iterator, qi::unused_type(), Skipper> constantBooleanFormulaDefinition; - qi::rule<Iterator, qi::unused_type(), Skipper> booleanFormulaDefinition; - - // Rules for variable recognition. - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanVariableCreatorExpression; - qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<std::shared_ptr<BaseExpression>>, Skipper> integerVariableCreatorExpression; - - storm::parser::prism::keywordsStruct keywords_; - storm::parser::prism::modelTypeStruct modelType_; - storm::parser::prism::relationalOperatorStruct relations_; - - /*! - * Adds a label with the given name and expression to the given label-to-expression map. - * - * @param name The name of the label. - * @param expression The expression associated with the label. - * @param nameToExpressionMap The map to which the label is added. - */ - void addLabel(std::string const& name, std::shared_ptr<BaseExpression> const& value, std::map<std::string, std::unique_ptr<BaseExpression>>& nameToExpressionMap); - - /*! - * Adds a boolean assignment for the given variable with the given expression and adds it to the - * provided variable-to-assignment map. - * - * @param variable The name of the variable that the assignment targets. - * @param expression The expression that is assigned to the variable. - * @param variableToAssignmentMap The map to which the assignment is added. - */ - void addBooleanAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& expression, std::map<std::string, Assignment>& variableToAssignmentMap); - - /*! - * Adds a boolean assignment for the given variable with the given expression and adds it to the - * provided variable-to-assignment map. - * - * @param variable The name of the variable that the assignment targets. - * @param expression The expression that is assigned to the variable. - * @param variableToAssignmentMap The map to which the assignment is added. - */ - void addIntegerAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& expression, std::map<std::string, Assignment>& variableToAssignmentMap); - - void addUndefinedBooleanConstant(std::string const& name, std::map<std::string, std::unique_ptr<BooleanConstantExpression>>& nameToExpressionMap); - - void addUndefinedIntegerConstant(std::string const& name, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>& nameToExpressionMap); - - void addUndefinedDoubleConstant(std::string const& name, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>& nameToExpressionMap); - - /*! - * Creates a module by renaming, i.e. takes the module given by the old name, creates a new module - * with the given name which renames all identifiers according to the given mapping. - * - * @param name The name of the new module. - * @param oldName The name of the module that is to be copied (modulo renaming). - * @param renaming A mapping from identifiers to their new names. - */ - Module renameModule(std::string const& name, std::string const& oldName, std::map<std::string, std::string> const& renaming); - - /*! - * Creates a new module with the given name, boolean and integer variables and commands. - * - * @param name The name of the module to create. - * @param booleanVariables The boolean variables of the module. - * @param integerVariables The integer variables of the module. - * @param booleanVariableToLocalIndexMap A mapping of boolean variables to module-local indices. - * @param integerVariableToLocalIndexMap A mapping of boolean variables to module-local indices. - * @param commands The commands associated with this module. - */ - Module createModule(std::string const& name, std::vector<BooleanVariable> const& booleanVariables, std::vector<IntegerVariable> const& integerVariables, std::map<std::string, uint_fast64_t> const& booleanVariableToLocalIndexMap, std::map<std::string, uint_fast64_t> const& integerVariableToLocalIndexMap, std::vector<storm::ir::Command> const& commands); - - /*! - * Creates an integer variable with the given name, domain and initial value and adds it to the - * provided list of integer variables and the given mappings. - * - * @param name The name of the integer variable. - * @param lower The expression that defines the lower bound of the domain. - * @param upper The expression that defines the upper bound of the domain. - * @param init The expression that defines the initial value of the variable. - * @param integerVariableToGlobalIndexMap A mapping of integer variables to global indices. - * @param isGlobalVariable A flag indicating whether the variable is supposed to be global or not. - */ - void createIntegerVariable(std::string const& name, std::shared_ptr<BaseExpression> const& lower, std::shared_ptr<BaseExpression> const& upper, std::shared_ptr<BaseExpression> const& init, std::vector<IntegerVariable>& integerVariables, std::map<std::string, uint_fast64_t>& integerVariableToGlobalIndexMap, bool isGlobalVariable); - - /*! - * Creates an boolean variable with the given name and initial value and adds it to the - * provided list of boolean variables and the given mappings. - * - * @param name The name of the boolean variable. - * @param init The expression that defines the initial value of the variable. - * @param booleanVariableToGlobalIndexMap A mapping of boolean variables to global indices. - * @param isGlobalVariable A flag indicating whether the variable is supposed to be global or not. - */ - void createBooleanVariable(std::string const& name, std::shared_ptr<BaseExpression> const& init, std::vector<BooleanVariable>& booleanVariables, std::map<std::string, uint_fast64_t>& booleanVariableToGlobalIndexMap, bool isGlobalVariable); - - /*! - * Creates a command with the given label, guard and updates. - * - * @param label The label of the command. - * @param guard The guard of the command. - * @param updates The updates associated with the command. - */ - Command createCommand(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::vector<Update> const& updates); - - /*! - * Creates an update with the given likelihood and the given assignments to boolean and integer variables, respectively. - * - * @param likelihood The likelihood of this update being executed. - * @param booleanAssignments The assignments to boolean variables this update involves. - * @param integerAssignments The assignments to integer variables this update involves. - */ - Update createUpdate(std::shared_ptr<BaseExpression> const& likelihood, std::map<std::string, Assignment> const& booleanAssignments, std::map<std::string, Assignment> const& integerAssignments); - - }; - - - } // namespace prism - } // namespace parser -} // namespace storm - - -#endif /* STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H */ - diff --git a/src/parser/prismparser/Tokens.h b/src/parser/prismparser/Tokens.h deleted file mode 100644 index bbf7e8418..000000000 --- a/src/parser/prismparser/Tokens.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * File: Tokens.h - * Author: nafur - * - * Created on April 19, 2013, 11:17 PM - */ - -#ifndef TOKENS_H -#define TOKENS_H - -namespace storm { -namespace parser { -namespace prism { - - /*! - * A structure mapping the textual representation of a model type to the model type - * representation of the intermediate representation. - */ - struct modelTypeStruct : qi::symbols<char, Program::ModelType> { - modelTypeStruct() { - add - ("dtmc", Program::ModelType::DTMC) - ("ctmc", Program::ModelType::CTMC) - ("mdp", Program::ModelType::MDP) - ("ctmdp", Program::ModelType::CTMDP) - ; - } - }; - - - /*! - * A structure defining the keywords that are not allowed to be chosen as identifiers. - */ - struct keywordsStruct : qi::symbols<char, unsigned> { - keywordsStruct() { - add - ("dtmc", 1) - ("ctmc", 2) - ("mdp", 3) - ("ctmdp", 4) - ("const", 5) - ("int", 6) - ("bool", 7) - ("module", 8) - ("endmodule", 9) - ("rewards", 10) - ("endrewards", 11) - ("true", 12) - ("false", 13) - ; - } - }; - - /*! - * A structure mapping the textual representation of a binary relation to the representation - * of the intermediate representation. - */ - struct relationalOperatorStruct : qi::symbols<char, BinaryRelationExpression::RelationType> { - relationalOperatorStruct() { - add - ("=", BinaryRelationExpression::EQUAL) - ("!=", BinaryRelationExpression::NOT_EQUAL) - ("<", BinaryRelationExpression::LESS) - ("<=", BinaryRelationExpression::LESS_OR_EQUAL) - (">", BinaryRelationExpression::GREATER) - (">=", BinaryRelationExpression::GREATER_OR_EQUAL) - ; - } - }; -} -} -} - -#endif /* TOKENS_H */ - diff --git a/src/parser/prismparser/VariableState.cpp b/src/parser/prismparser/VariableState.cpp deleted file mode 100644 index 244a3f17e..000000000 --- a/src/parser/prismparser/VariableState.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "VariableState.h" -#include "src/exceptions/InvalidArgumentException.h" - -namespace storm { - namespace parser { - namespace prism { - - using namespace storm::ir; - using namespace storm::ir::expressions; - - template<typename T> - struct SymbolDump { - SymbolDump(std::ostream& out) : out(out) {} - void operator() (std::basic_string<char> s, T elem) { - this->out << "\t" << s << " -> " << elem << std::endl; - } - private: - std::ostream& out; - }; - template<typename T> - std::ostream& operator<<(std::ostream& out, qi::symbols<char, T>& symbols) { - out << "Dumping symbol table" << std::endl; - SymbolDump<T> dump(out); - symbols.for_each(dump); - return out; - } - std::ostream& operator<<(std::ostream& out, VariableState::variableNamesStruct& symbols) { - SymbolDump<std::string> dump(out); - symbols.for_each(dump); - return out; - } - - - VariableState::VariableState(bool firstRun) : firstRun(firstRun), keywords(), nextLocalBooleanVariableIndex(0), nextLocalIntegerVariableIndex(0), nextGlobalBooleanVariableIndex(0), nextGlobalIntegerVariableIndex(0), nextGlobalCommandIndex(0), nextGlobalUpdateIndex(0) { - // Nothing to do here. - } - - uint_fast64_t VariableState::getNextLocalBooleanVariableIndex() const { - return this->nextLocalBooleanVariableIndex; - } - - uint_fast64_t VariableState::getNextLocalIntegerVariableIndex() const { - return this->nextLocalIntegerVariableIndex; - } - - uint_fast64_t VariableState::getNextGlobalBooleanVariableIndex() const { - return this->nextGlobalBooleanVariableIndex; - } - - uint_fast64_t VariableState::getNextGlobalIntegerVariableIndex() const { - return this->nextGlobalIntegerVariableIndex; - } - - uint_fast64_t VariableState::getNextGlobalCommandIndex() const { - return this->nextGlobalCommandIndex; - } - - uint_fast64_t VariableState::getNextGlobalUpdateIndex() const { - return this->nextGlobalUpdateIndex; - } - - uint_fast64_t VariableState::addBooleanVariable(std::string const& name) { - if (firstRun) { - LOG4CPLUS_TRACE(logger, "Adding boolean variable " << name << " with new id " << this->nextGlobalBooleanVariableIndex << "."); - this->booleanVariables_.add(name, std::shared_ptr<VariableExpression>(new VariableExpression(storm::ir::expressions::BaseExpression::bool_, this->nextGlobalBooleanVariableIndex, name))); - this->booleanVariableNames_.add(name, name); - ++this->nextGlobalBooleanVariableIndex; - ++this->nextLocalBooleanVariableIndex; - return this->nextGlobalBooleanVariableIndex - 1; - } else { - std::shared_ptr<VariableExpression> variableExpression = this->booleanVariables_.at(name); - if (variableExpression != nullptr) { - return variableExpression->getGlobalVariableIndex(); - } else { - LOG4CPLUS_ERROR(logger, "Boolean variable " << name << " does not exist."); - throw storm::exceptions::InvalidArgumentException() << "Boolean variable " << name << " does not exist."; - } - } - } - - uint_fast64_t VariableState::addIntegerVariable(std::string const& name) { - if (firstRun) { - LOG4CPLUS_TRACE(logger, "Adding integer variable " << name << " with new id " << this->nextGlobalIntegerVariableIndex << "."); - this->integerVariables_.add(name, std::shared_ptr<VariableExpression>(new VariableExpression(storm::ir::expressions::BaseExpression::int_, this->nextGlobalIntegerVariableIndex, name))); - this->integerVariableNames_.add(name, name); - ++this->nextGlobalIntegerVariableIndex; - ++this->nextLocalIntegerVariableIndex; - return this->nextGlobalIntegerVariableIndex - 1; - } else { - std::shared_ptr<VariableExpression> variableExpression = this->integerVariables_.at(name); - if (variableExpression != nullptr) { - return variableExpression->getGlobalVariableIndex(); - } else { - LOG4CPLUS_ERROR(logger, "Integer variable " << name << " does not exist."); - throw storm::exceptions::InvalidArgumentException() << "Integer variable " << name << " does not exist."; - } - } - } - - std::shared_ptr<VariableExpression> VariableState::getBooleanVariableExpression(std::string const& name) const { - std::shared_ptr<VariableExpression> const* variableExpression = this->booleanVariables_.find(name); - if (variableExpression != nullptr) { - return *variableExpression; - } else { - if (firstRun) { - LOG4CPLUS_TRACE(logger, "Trying to retrieve boolean variable " << name << " that was not yet created; returning dummy instead."); - return std::shared_ptr<VariableExpression>(new VariableExpression(BaseExpression::bool_, name)); - } else { - LOG4CPLUS_ERROR(logger, "Boolean variable " << name << " does not exist."); - throw storm::exceptions::InvalidArgumentException() << "Boolean variable " << name << " does not exist."; - } - } - } - - std::shared_ptr<VariableExpression> VariableState::getIntegerVariableExpression(std::string const& name) const { - std::shared_ptr<VariableExpression> const* variableExpression = this->integerVariables_.find(name); - if (variableExpression != nullptr) { - return *variableExpression; - } else { - if (firstRun) { - LOG4CPLUS_TRACE(logger, "Trying to retrieve integer variable " << name << " that was not yet created; returning dummy instead."); - return std::shared_ptr<VariableExpression>(new VariableExpression(BaseExpression::int_, name)); - } else { - LOG4CPLUS_ERROR(logger, "Integer variable " << name << " does not exist."); - throw storm::exceptions::InvalidArgumentException() << "Integer variable " << name << " does not exist."; - } - } - } - - std::shared_ptr<VariableExpression> VariableState::getVariableExpression(std::string const& name) const { - std::shared_ptr<VariableExpression> const* variableExpression = this->integerVariables_.find(name); - if (variableExpression != nullptr) { - return *variableExpression; - } - - variableExpression = this->booleanVariables_.find(name); - if (variableExpression != nullptr) { - return *variableExpression; - } - LOG4CPLUS_ERROR(logger, "Variable " << name << " does not exist."); - throw storm::exceptions::InvalidArgumentException() << "Variable " << name << " does not exist."; - } - - void VariableState::clearLocalVariables() { - this->localBooleanVariables_.clear(); - this->localIntegerVariables_.clear(); - this->nextLocalBooleanVariableIndex = 0; - this->nextLocalIntegerVariableIndex = 0; - } - - bool VariableState::isFreeIdentifier(std::string const& identifier) const { - if (this->booleanVariableNames_.find(identifier) != nullptr) return false; - if (this->integerVariableNames_.find(identifier) != nullptr) return false; - if (this->allConstantNames_.find(identifier) != nullptr) return false; - if (this->labelNames_.find(identifier) != nullptr) return false; - if (this->moduleNames_.find(identifier) != nullptr) return false; - if (this->keywords.find(identifier) != nullptr) return false; - if (this->booleanFormulas_.find(identifier) != nullptr) return false; - if (this->integerFormulas_.find(identifier) != nullptr) return false; - if (this->doubleFormulas_.find(identifier) != nullptr) return false; - if (this->constantBooleanFormulas_.find(identifier) != nullptr) return false; - if (this->constantIntegerFormulas_.find(identifier) != nullptr) return false; - if (this->constantDoubleFormulas_.find(identifier) != nullptr) return false; - return true; - } - - bool VariableState::isIdentifier(std::string const& identifier) const { - if (this->allConstantNames_.find(identifier) != nullptr) return false; - if (this->keywords.find(identifier) != nullptr) return false; - return true; - } - - void VariableState::prepareForSecondRun() { - integerConstants_.clear(); - booleanConstants_.clear(); - doubleConstants_.clear(); - allConstantNames_.clear(); - constantBooleanFormulas_.clear(); - booleanFormulas_.clear(); - constantIntegerFormulas_.clear(); - integerFormulas_.clear(); - constantDoubleFormulas_.clear(); - doubleFormulas_.clear(); - this->firstRun = false; - nextGlobalCommandIndex = 0; - nextGlobalUpdateIndex = 0; - } - - } // namespace prism - } // namespace parser -} // namespace storm diff --git a/src/parser/prismparser/VariableState.h b/src/parser/prismparser/VariableState.h deleted file mode 100644 index 6dc7170a4..000000000 --- a/src/parser/prismparser/VariableState.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * File: VariableState.h - * Author: nafur - * - * Created on April 10, 2013, 4:43 PM - */ - -#ifndef STORM_PARSER_PRISMPARSER_VARIABLESTATE_H -#define STORM_PARSER_PRISMPARSER_VARIABLESTATE_H - -#include <iostream> - -#include "src/ir/IR.h" -#include "Includes.h" -#include "Tokens.h" - -namespace storm { - namespace parser { - namespace prism { - - using namespace storm::ir; - using namespace storm::ir::expressions; - - template<typename T> - std::ostream& operator<<(std::ostream& out, qi::symbols<char, T>& symbols); - - /*! - * This class contains the internal state that is needed for parsing a PRISM model. - */ - class VariableState { - public: - /*! - * Creates a new variable state object. By default, this object will be set to a state in which - * it is ready for performing a first run on some input. The first run creates all variables - * while the second one checks for the correct usage of variables in expressions. - * - * @param firstRun If set, this object will be in a state ready for performing the first run. If - * set to false, this object will assume that it has all variable data already. - */ - VariableState(bool firstRun = true); - - /*! - * Indicator, if we are still in the first run. - */ - bool firstRun; - - /*! - * A parser for all reserved keywords. - */ - keywordsStruct keywords; - - /*! - * Internal counter for the local index of the next new boolean variable. - */ - uint_fast64_t nextLocalBooleanVariableIndex; - - /*! - * Retrieves the next free local index for a boolean variable. - * - * @return The next free local index for a boolean variable. - */ - uint_fast64_t getNextLocalBooleanVariableIndex() const; - - /*! - * Internal counter for the local index of the next new integer variable. - */ - uint_fast64_t nextLocalIntegerVariableIndex; - - /*! - * Retrieves the next free global index for a integer variable. - * - * @return The next free global index for a integer variable. - */ - uint_fast64_t getNextLocalIntegerVariableIndex() const; - - /*! - * Internal counter for the index of the next new boolean variable. - */ - uint_fast64_t nextGlobalBooleanVariableIndex; - - /*! - * Retrieves the next free global index for a boolean variable. - * - * @return The next free global index for a boolean variable. - */ - uint_fast64_t getNextGlobalBooleanVariableIndex() const; - - /*! - * Internal counter for the index of the next new integer variable. - */ - uint_fast64_t nextGlobalIntegerVariableIndex; - - /*! - * Retrieves the next free global index for a integer variable. - * - * @return The next free global index for a integer variable. - */ - uint_fast64_t getNextGlobalIntegerVariableIndex() const; - - /*! - * Internal counter for the index of the next command. - */ - uint_fast64_t nextGlobalCommandIndex; - - /*! - * Retrieves the next free global index for a command. - * - * @return The next free global index for a command. - */ - uint_fast64_t getNextGlobalCommandIndex() const; - - /*! - * Internal counter for the index of the next update. - */ - uint_fast64_t nextGlobalUpdateIndex; - - /*! - * Retrieves the next free global index for an update. - * - * @return The next free global index for an update. - */ - uint_fast64_t getNextGlobalUpdateIndex() const; - - // Structures mapping variable and constant names to the corresponding expression nodes of - // the intermediate representation. - struct qi::symbols<char, std::shared_ptr<VariableExpression>> integerVariables_, booleanVariables_; - struct qi::symbols<char, std::shared_ptr<BaseExpression>> integerConstants_, booleanConstants_, doubleConstants_, booleanFormulas_, constantBooleanFormulas_, integerFormulas_, constantIntegerFormulas_, doubleFormulas_, constantDoubleFormulas_; - - // A structure representing the identity function over identifier names. - struct variableNamesStruct : qi::symbols<char, std::string> { } - integerVariableNames_, booleanVariableNames_, commandNames_, labelNames_, allConstantNames_, moduleNames_, - localBooleanVariables_, localIntegerVariables_, assignedBooleanVariables_, assignedIntegerVariables_, - globalBooleanVariables_, globalIntegerVariables_; - - /*! - * Adds a new boolean variable with the given name. - * - * @param name The name of the variable. - * @return The global index of the variable. - */ - uint_fast64_t addBooleanVariable(std::string const& name); - - /*! - * Adds a new integer variable with the given name. - * - * @param name The name of the variable. - * @return The global index of the variable. - */ - uint_fast64_t addIntegerVariable(std::string const& name); - - /*! - * Retrieves the variable expression for the boolean variable with the given name. - * - * @param name The name of the boolean variable for which to retrieve the variable expression. - * @return The variable expression for the boolean variable with the given name. - */ - std::shared_ptr<VariableExpression> getBooleanVariableExpression(std::string const& name) const; - - /*! - * Retrieves the variable expression for the integer variable with the given name. - * - * @param name The name of the integer variable for which to retrieve the variable expression. - * @return The variable expression for the integer variable with the given name. - */ - std::shared_ptr<VariableExpression> getIntegerVariableExpression(std::string const& name) const; - - /*! - * Retrieve the variable expression for the variable with the given name. - * - * @param name The name of the variable for which to retrieve the variable expression. - * @return The variable expression for the variable with the given name. - */ - std::shared_ptr<VariableExpression> getVariableExpression(std::string const& name) const; - - /*! - * Clears all local variables. - */ - void clearLocalVariables(); - - /*! - * Check if the given string is a free identifier. - * - * @param identifier A string to be checked. - * @return True iff the given string is a free identifier. - */ - bool isFreeIdentifier(std::string const& identifier) const; - - /*! - * Check if given string is a valid identifier. - * - * @param identifier A string to be checked. - * @return True iff the given string is an identifier. - */ - bool isIdentifier(std::string const& identifier) const; - - /*! - * Prepare state to proceed to second parser run. Currently, this clears the constants. - */ - void prepareForSecondRun(); - }; - - } // namespace prism - } // namespace parser -} // namespace storm - -#endif /* STORM_PARSER_PRISMPARSER_VARIABLESTATE_H */ - diff --git a/src/solver/GurobiLpSolver.cpp b/src/solver/GurobiLpSolver.cpp index c06233942..75a0d5a7e 100644 --- a/src/solver/GurobiLpSolver.cpp +++ b/src/solver/GurobiLpSolver.cpp @@ -1,6 +1,7 @@ #include "src/solver/GurobiLpSolver.h" #ifdef STORM_HAVE_GUROBI +#include <numeric> #include "src/exceptions/InvalidStateException.h" #include "src/settings/Settings.h" @@ -162,12 +163,29 @@ namespace storm { throw storm::exceptions::InvalidStateException() << "Sizes of variable indices vector and coefficients vector do not match."; } - // Convert the uint vector to ints for proper input to Gurobi. - std::vector<int> variablesCopy(variables.begin(), variables.end()); + // As Gurobi requires the indices to be unique, we now explicitly make them unique. For this, we sort the + // variables and coefficients and eliminated duplicates by adding the coefficients. - // Copy the coefficients, because Gurobi does not take the coefficients as const values. The alternative to this would be casting - // away the constness, which gives undefined behaviour if Gurobi actually modifies something. - std::vector<double> coefficientsCopy(coefficients); + // We start by sorting both vectors. + std::vector<uint_fast64_t> sortedVariables(variables); + std::vector<double> sortedCoefficients(coefficients); + std::vector<uint_fast64_t> permutation(variables.size()); + std::iota(permutation.begin(), permutation.end(), 0); + std::sort(permutation.begin(), permutation.end(), [&] (uint_fast64_t i, uint_fast64_t j) { return variables[i] < variables[j]; } ); + std::transform(permutation.begin(), permutation.end(), sortedVariables.begin(), [&] (uint_fast64_t i) { return variables[i]; } ); + std::transform(permutation.begin(), permutation.end(), sortedCoefficients.begin(), [&] (uint_fast64_t i) { return coefficients[i]; } ); + + // Now we perform the duplicate elimination step. + std::vector<int> uniqueVariables; + std::vector<double> uniqueCoefficients; + for (uint_fast64_t i = 0; i < sortedVariables.size(); ++i) { + if (!uniqueVariables.empty() && uniqueVariables.back() == sortedVariables[i]) { + uniqueCoefficients.back() += sortedCoefficients[i]; + } else { + uniqueVariables.push_back(static_cast<int>(sortedVariables[i])); + uniqueCoefficients.push_back(sortedCoefficients[i]); + } + } bool strictBound = boundType == LESS || boundType == GREATER; char sense = boundType == LESS || boundType == LESS_EQUAL ? GRB_LESS_EQUAL : boundType == EQUAL ? GRB_EQUAL : GRB_GREATER_EQUAL; @@ -181,7 +199,7 @@ namespace storm { rightHandSideValue += storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); } } - int error = GRBaddconstr(model, variablesCopy.size(), variablesCopy.data(), coefficientsCopy.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str()); + int error = GRBaddconstr(model, uniqueVariables.size(), uniqueVariables.data(), uniqueCoefficients.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str()); if (error) { LOG4CPLUS_ERROR(logger, "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ", error code " << error << ")."); diff --git a/src/storage/dd/CuddDd.cpp b/src/storage/dd/CuddDd.cpp index eba51a557..0e163c5f7 100644 --- a/src/storage/dd/CuddDd.cpp +++ b/src/storage/dd/CuddDd.cpp @@ -7,22 +7,26 @@ namespace storm { namespace dd { - Dd<CUDD>::Dd(std::shared_ptr<DdManager<CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames) : ddManager(ddManager), cuddAdd(cuddAdd), containedMetaVariableNames(containedMetaVariableNames) { + Dd<DdType::CUDD>::Dd(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames) : ddManager(ddManager), cuddAdd(cuddAdd), containedMetaVariableNames(containedMetaVariableNames) { // Intentionally left empty. } - bool Dd<CUDD>::operator==(Dd<CUDD> const& other) const { - return this->getCuddAdd() == other.getCuddAdd(); + bool Dd<DdType::CUDD>::operator==(Dd<DdType::CUDD> const& other) const { + return this->cuddAdd == other.getCuddAdd(); } - Dd<CUDD> Dd<CUDD>::operator+(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); + bool Dd<DdType::CUDD>::operator!=(Dd<DdType::CUDD> const& other) const { + return this->cuddAdd != other.getCuddAdd(); + } + + Dd<DdType::CUDD> Dd<DdType::CUDD>::operator+(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); result += other; return result; } - Dd<CUDD>& Dd<CUDD>::operator+=(Dd<CUDD> const& other) { - this->getCuddAdd() += other.getCuddAdd(); + Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator+=(Dd<DdType::CUDD> const& other) { + this->cuddAdd += other.getCuddAdd(); // Join the variable sets of the two participating DDs. this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end()); @@ -30,14 +34,14 @@ namespace storm { return *this; } - Dd<CUDD> Dd<CUDD>::operator*(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); + Dd<DdType::CUDD> Dd<DdType::CUDD>::operator*(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); result *= other; return result; } - Dd<CUDD>& Dd<CUDD>::operator*=(Dd<CUDD> const& other) { - this->getCuddAdd() *= other.getCuddAdd(); + Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator*=(Dd<DdType::CUDD> const& other) { + this->cuddAdd *= other.getCuddAdd(); // Join the variable sets of the two participating DDs. this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end()); @@ -45,14 +49,14 @@ namespace storm { return *this; } - Dd<CUDD> Dd<CUDD>::operator-(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); + Dd<DdType::CUDD> Dd<DdType::CUDD>::operator-(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); result -= other; return result; } - Dd<CUDD>& Dd<CUDD>::operator-=(Dd<CUDD> const& other) { - this->getCuddAdd() -= other.getCuddAdd(); + Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator-=(Dd<DdType::CUDD> const& other) { + this->cuddAdd -= other.getCuddAdd(); // Join the variable sets of the two participating DDs. this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end()); @@ -60,14 +64,14 @@ namespace storm { return *this; } - Dd<CUDD> Dd<CUDD>::operator/(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); + Dd<DdType::CUDD> Dd<DdType::CUDD>::operator/(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); result /= other; return result; } - Dd<CUDD>& Dd<CUDD>::operator/=(Dd<CUDD> const& other) { - this->getCuddAdd().Divide(other.getCuddAdd()); + Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator/=(Dd<DdType::CUDD> const& other) { + this->cuddAdd = this->cuddAdd.Divide(other.getCuddAdd()); // Join the variable sets of the two participating DDs. this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end()); @@ -75,55 +79,55 @@ namespace storm { return *this; } - Dd<CUDD> Dd<CUDD>::operator~() const { - Dd<CUDD> result(*this); + Dd<DdType::CUDD> Dd<DdType::CUDD>::operator~() const { + Dd<DdType::CUDD> result(*this); result.complement(); return result; } - Dd<CUDD>& Dd<CUDD>::complement() { - this->getCuddAdd() = ~this->getCuddAdd(); + Dd<DdType::CUDD>& Dd<DdType::CUDD>::complement() { + this->cuddAdd = ~this->cuddAdd; return *this; } - Dd<CUDD> Dd<CUDD>::equals(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); - result.getCuddAdd().Equals(other.getCuddAdd()); + Dd<DdType::CUDD> Dd<DdType::CUDD>::equals(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); + result.cuddAdd = result.cuddAdd.Equals(other.getCuddAdd()); return result; } - Dd<CUDD> Dd<CUDD>::notEquals(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); - result.getCuddAdd().NotEquals(other.getCuddAdd()); + Dd<DdType::CUDD> Dd<DdType::CUDD>::notEquals(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); + result.cuddAdd = result.cuddAdd.NotEquals(other.getCuddAdd()); return result; } - Dd<CUDD> Dd<CUDD>::less(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); - result.getCuddAdd().LessThan(other.getCuddAdd()); + Dd<DdType::CUDD> Dd<DdType::CUDD>::less(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); + result.cuddAdd = result.cuddAdd.LessThan(other.getCuddAdd()); return result; } - Dd<CUDD> Dd<CUDD>::lessOrEqual(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); - result.getCuddAdd().LessThanOrEqual(other.getCuddAdd()); + Dd<DdType::CUDD> Dd<DdType::CUDD>::lessOrEqual(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); + result.cuddAdd = result.cuddAdd.LessThanOrEqual(other.getCuddAdd()); return result; } - Dd<CUDD> Dd<CUDD>::greater(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); - result.getCuddAdd().GreaterThan(other.getCuddAdd()); + Dd<DdType::CUDD> Dd<DdType::CUDD>::greater(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); + result.cuddAdd = result.cuddAdd.GreaterThan(other.getCuddAdd()); return result; } - Dd<CUDD> Dd<CUDD>::greaterOrEqual(Dd<CUDD> const& other) const { - Dd<CUDD> result(*this); - result.getCuddAdd().GreaterThanOrEqual(other.getCuddAdd()); + Dd<DdType::CUDD> Dd<DdType::CUDD>::greaterOrEqual(Dd<DdType::CUDD> const& other) const { + Dd<DdType::CUDD> result(*this); + result.cuddAdd = result.cuddAdd.GreaterThanOrEqual(other.getCuddAdd()); return result; } - void Dd<CUDD>::existsAbstract(std::set<std::string> const& metaVariableNames) { - Dd<CUDD> cubeDd(this->getDdManager()->getOne()); + void Dd<DdType::CUDD>::existsAbstract(std::set<std::string> const& metaVariableNames) { + Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne()); for (auto const& metaVariableName : metaVariableNames) { // First check whether the DD contains the meta variable and erase it, if this is the case. @@ -132,15 +136,15 @@ namespace storm { } this->getContainedMetaVariableNames().erase(metaVariableName); - DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); + DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); cubeDd *= metaVariable.getCube(); } - this->getCuddAdd().OrAbstract(cubeDd.getCuddAdd()); + this->cuddAdd = this->cuddAdd.OrAbstract(cubeDd.getCuddAdd()); } - void Dd<CUDD>::sumAbstract(std::set<std::string> const& metaVariableNames) { - Dd<CUDD> cubeDd(this->getDdManager()->getOne()); + void Dd<DdType::CUDD>::sumAbstract(std::set<std::string> const& metaVariableNames) { + Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne()); for (auto const& metaVariableName : metaVariableNames) { // First check whether the DD contains the meta variable and erase it, if this is the case. @@ -149,15 +153,15 @@ namespace storm { } this->getContainedMetaVariableNames().erase(metaVariableName); - DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); + DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); cubeDd *= metaVariable.getCube(); } - this->getCuddAdd().ExistAbstract(cubeDd.getCuddAdd()); + this->cuddAdd = this->cuddAdd.ExistAbstract(cubeDd.getCuddAdd()); } - void Dd<CUDD>::minAbstract(std::set<std::string> const& metaVariableNames) { - Dd<CUDD> cubeDd(this->getDdManager()->getOne()); + void Dd<DdType::CUDD>::minAbstract(std::set<std::string> const& metaVariableNames) { + Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne()); for (auto const& metaVariableName : metaVariableNames) { // First check whether the DD contains the meta variable and erase it, if this is the case. @@ -166,15 +170,15 @@ namespace storm { } this->getContainedMetaVariableNames().erase(metaVariableName); - DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); + DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); cubeDd *= metaVariable.getCube(); } - this->getCuddAdd().Minimum(cubeDd.getCuddAdd()); + this->cuddAdd = this->cuddAdd.MinAbstract(cubeDd.getCuddAdd()); } - void Dd<CUDD>::maxAbstract(std::set<std::string> const& metaVariableNames) { - Dd<CUDD> cubeDd(this->getDdManager()->getOne()); + void Dd<DdType::CUDD>::maxAbstract(std::set<std::string> const& metaVariableNames) { + Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne()); for (auto const& metaVariableName : metaVariableNames) { // First check whether the DD contains the meta variable and erase it, if this is the case. @@ -183,19 +187,19 @@ namespace storm { } this->getContainedMetaVariableNames().erase(metaVariableName); - DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); + DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName); cubeDd *= metaVariable.getCube(); } - this->getCuddAdd().Maximum(cubeDd.getCuddAdd()); + this->cuddAdd = this->cuddAdd.MaxAbstract(cubeDd.getCuddAdd()); } - void Dd<CUDD>::swapVariables(std::vector<std::pair<std::string, std::string>> const& metaVariablePairs) { + void Dd<DdType::CUDD>::swapVariables(std::vector<std::pair<std::string, std::string>> const& metaVariablePairs) { std::vector<ADD> from; std::vector<ADD> to; for (auto const& metaVariablePair : metaVariablePairs) { - DdMetaVariable<CUDD> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first); - DdMetaVariable<CUDD> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second); + DdMetaVariable<DdType::CUDD> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first); + DdMetaVariable<DdType::CUDD> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second); // Check if it's legal so swap the meta variables. if (variable1.getNumberOfDdVariables() != variable2.getNumberOfDdVariables()) { @@ -223,10 +227,10 @@ namespace storm { } // Finally, call CUDD to swap the variables. - this->getCuddAdd().SwapVariables(from, to); + this->cuddAdd = this->cuddAdd.SwapVariables(from, to); } - Dd<CUDD> Dd<CUDD>::multiplyMatrix(Dd<CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames) { + Dd<DdType::CUDD> Dd<DdType::CUDD>::multiplyMatrix(Dd<DdType::CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames) { std::vector<ADD> summationDdVariables; // Create the CUDD summation variables. @@ -241,11 +245,10 @@ namespace storm { std::set<std::string> containedMetaVariableNames; std::set_difference(unionOfMetaVariableNames.begin(), unionOfMetaVariableNames.end(), summationMetaVariableNames.begin(), summationMetaVariableNames.end(), std::inserter(containedMetaVariableNames, containedMetaVariableNames.begin())); - return Dd<CUDD>(this->getDdManager(), this->getCuddAdd().MatrixMultiply(otherMatrix.getCuddAdd(), summationDdVariables), containedMetaVariableNames); + return Dd<DdType::CUDD>(this->getDdManager(), this->cuddAdd.MatrixMultiply(otherMatrix.getCuddAdd(), summationDdVariables), containedMetaVariableNames); } - - uint_fast64_t Dd<CUDD>::getNonZeroCount() const { + uint_fast64_t Dd<DdType::CUDD>::getNonZeroCount() const { std::size_t numberOfDdVariables = 0; for (auto const& metaVariableName : this->containedMetaVariableNames) { numberOfDdVariables += this->getDdManager()->getMetaVariable(metaVariableName).getNumberOfDdVariables(); @@ -253,60 +256,85 @@ namespace storm { return static_cast<uint_fast64_t>(this->cuddAdd.CountMinterm(static_cast<int>(numberOfDdVariables))); } - uint_fast64_t Dd<CUDD>::getLeafCount() const { + uint_fast64_t Dd<DdType::CUDD>::getLeafCount() const { return static_cast<uint_fast64_t>(this->cuddAdd.CountLeaves()); } - uint_fast64_t Dd<CUDD>::getNodeCount() const { + uint_fast64_t Dd<DdType::CUDD>::getNodeCount() const { return static_cast<uint_fast64_t>(this->cuddAdd.nodeCount()); } - double Dd<CUDD>::getMin() const { - ADD constantMinAdd = this->getCuddAdd().FindMin(); + double Dd<DdType::CUDD>::getMin() const { + ADD constantMinAdd = this->cuddAdd.FindMin(); return static_cast<double>(Cudd_V(constantMinAdd.getNode())); } - double Dd<CUDD>::getMax() const { - ADD constantMaxAdd = this->getCuddAdd().FindMax(); + double Dd<DdType::CUDD>::getMax() const { + ADD constantMaxAdd = this->cuddAdd.FindMax(); return static_cast<double>(Cudd_V(constantMaxAdd.getNode())); } - void Dd<CUDD>::setValue(std::string const& metaVariableName, int_fast64_t variableValue, double targetValue) { - std::unordered_map<std::string, int_fast64_t> metaVariableNameToValueMap; + void Dd<DdType::CUDD>::setValue(std::string const& metaVariableName, int_fast64_t variableValue, double targetValue) { + std::map<std::string, int_fast64_t> metaVariableNameToValueMap; metaVariableNameToValueMap.emplace(metaVariableName, variableValue); this->setValue(metaVariableNameToValueMap, targetValue); } - void Dd<CUDD>::setValue(std::string const& metaVariableName1, int_fast64_t variableValue1, std::string const& metaVariableName2, int_fast64_t variableValue2, double targetValue) { - std::unordered_map<std::string, int_fast64_t> metaVariableNameToValueMap; + void Dd<DdType::CUDD>::setValue(std::string const& metaVariableName1, int_fast64_t variableValue1, std::string const& metaVariableName2, int_fast64_t variableValue2, double targetValue) { + std::map<std::string, int_fast64_t> metaVariableNameToValueMap; metaVariableNameToValueMap.emplace(metaVariableName1, variableValue1); metaVariableNameToValueMap.emplace(metaVariableName2, variableValue2); this->setValue(metaVariableNameToValueMap, targetValue); } - void Dd<CUDD>::setValue(std::unordered_map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue) { - Dd<CUDD> valueEncoding(this->getDdManager()->getOne()); + void Dd<DdType::CUDD>::setValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue) { + Dd<DdType::CUDD> valueEncoding(this->getDdManager()->getOne()); + for (auto const& nameValuePair : metaVariableNameToValueMap) { + valueEncoding *= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second); + // Also record that the DD now contains the meta variable. + this->addContainedMetaVariable(nameValuePair.first); + } + + this->cuddAdd = valueEncoding.getCuddAdd().Ite(this->getDdManager()->getConstant(targetValue).getCuddAdd(), this->cuddAdd); + } + + double Dd<DdType::CUDD>::getValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap) const { + std::set<std::string> remainingMetaVariables(this->getContainedMetaVariableNames()); + Dd<DdType::CUDD> valueEncoding(this->getDdManager()->getOne()); for (auto const& nameValuePair : metaVariableNameToValueMap) { valueEncoding *= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second); + if (this->containsMetaVariable(nameValuePair.first)) { + remainingMetaVariables.erase(nameValuePair.first); + } + } + + if (!remainingMetaVariables.empty()) { + throw storm::exceptions::InvalidArgumentException() << "Cannot evaluate function for which not all inputs were given."; } - this->getCuddAdd() = valueEncoding.getCuddAdd().Ite(this->getDdManager()->getConstant(targetValue).getCuddAdd(), this->cuddAdd); + Dd<DdType::CUDD> value = *this * valueEncoding; + value.sumAbstract(this->getContainedMetaVariableNames()); + return static_cast<double>(Cudd_V(value.getCuddAdd().getNode())); } - bool Dd<CUDD>::isOne() const { + bool Dd<DdType::CUDD>::isOne() const { return *this == this->getDdManager()->getOne(); } - bool Dd<CUDD>::isZero() const { + bool Dd<DdType::CUDD>::isZero() const { return *this == this->getDdManager()->getZero(); } - bool Dd<CUDD>::containsMetaVariable(std::string const& metaVariableName) const { + bool Dd<DdType::CUDD>::isConstant() const { + return Cudd_IsConstant(this->cuddAdd.getNode()); + } + + bool Dd<DdType::CUDD>::containsMetaVariable(std::string const& metaVariableName) const { auto const& metaVariable = containedMetaVariableNames.find(metaVariableName); return metaVariable != containedMetaVariableNames.end(); } - bool Dd<CUDD>::containsMetaVariables(std::set<std::string> metaVariableNames) const { + bool Dd<DdType::CUDD>::containsMetaVariables(std::set<std::string> metaVariableNames) const { for (auto const& metaVariableName : metaVariableNames) { auto const& metaVariable = containedMetaVariableNames.find(metaVariableName); @@ -317,38 +345,49 @@ namespace storm { return true; } - std::set<std::string> const& Dd<CUDD>::getContainedMetaVariableNames() const { + std::set<std::string> const& Dd<DdType::CUDD>::getContainedMetaVariableNames() const { return this->containedMetaVariableNames; } - std::set<std::string>& Dd<CUDD>::getContainedMetaVariableNames() { + std::set<std::string>& Dd<DdType::CUDD>::getContainedMetaVariableNames() { return this->containedMetaVariableNames; } - void Dd<CUDD>::exportToDot(std::string const& filename) const { - FILE* filePointer = fopen(filename.c_str() , "w"); - this->getDdManager()->getCuddManager().DumpDot({this->cuddAdd}, nullptr, nullptr, filePointer); - fclose(filePointer); + void Dd<DdType::CUDD>::exportToDot(std::string const& filename) const { + std::vector<ADD> cuddAddVector = { this->cuddAdd }; + if (filename.empty()) { + this->getDdManager()->getCuddManager().DumpDot(cuddAddVector); + } else { + FILE* filePointer = fopen(filename.c_str() , "w"); + this->getDdManager()->getCuddManager().DumpDot(cuddAddVector, nullptr, nullptr, filePointer); + fclose(filePointer); + } } - ADD Dd<CUDD>::getCuddAdd() { + ADD Dd<DdType::CUDD>::getCuddAdd() { return this->cuddAdd; } - ADD const& Dd<CUDD>::getCuddAdd() const { + ADD const& Dd<DdType::CUDD>::getCuddAdd() const { return this->cuddAdd; } - void Dd<CUDD>::addContainedMetaVariable(std::string const& metaVariableName) { + void Dd<DdType::CUDD>::addContainedMetaVariable(std::string const& metaVariableName) { this->getContainedMetaVariableNames().insert(metaVariableName); } - void Dd<CUDD>::removeContainedMetaVariable(std::string const& metaVariableName) { + void Dd<DdType::CUDD>::removeContainedMetaVariable(std::string const& metaVariableName) { this->getContainedMetaVariableNames().erase(metaVariableName); } - std::shared_ptr<DdManager<CUDD>> Dd<CUDD>::getDdManager() const { + std::shared_ptr<DdManager<DdType::CUDD>> Dd<DdType::CUDD>::getDdManager() const { return this->ddManager; } + + std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd) { + dd.exportToDot(); + return out; + } + } } \ No newline at end of file diff --git a/src/storage/dd/CuddDd.h b/src/storage/dd/CuddDd.h index 1f8339fe6..6da2dc9c3 100644 --- a/src/storage/dd/CuddDd.h +++ b/src/storage/dd/CuddDd.h @@ -1,9 +1,10 @@ #ifndef STORM_STORAGE_DD_CUDDDD_H_ #define STORM_STORAGE_DD_CUDDDD_H_ -#include <unordered_map> +#include <map> #include <set> #include <memory> +#include <iostream> #include "src/storage/dd/Dd.h" #include "src/utility/OsDetection.h" @@ -17,26 +18,35 @@ namespace storm { template<DdType Type> class DdManager; template<> - class Dd<CUDD> { + class Dd<DdType::CUDD> { public: // Declare the DdManager class as friend so it can access the internals of a DD. - friend class DdManager<CUDD>; + friend class DdManager<DdType::CUDD>; // Instantiate all copy/move constructors/assignments with the default implementation. Dd() = default; - Dd(Dd<CUDD> const& other) = default; - Dd& operator=(Dd<CUDD> const& other) = default; + Dd(Dd<DdType::CUDD> const& other) = default; + Dd& operator=(Dd<DdType::CUDD> const& other) = default; #ifndef WINDOWS - Dd(Dd<CUDD>&& other) = default; - Dd& operator=(Dd<CUDD>&& other) = default; + Dd(Dd<DdType::CUDD>&& other) = default; + Dd& operator=(Dd<DdType::CUDD>&& other) = default; #endif /*! * Retrieves whether the two DDs represent the same function. * * @param other The DD that is to be compared with the current one. + * @return True if the DDs represent the same function. */ - bool operator==(Dd<CUDD> const& other) const; + bool operator==(Dd<DdType::CUDD> const& other) const; + + /*! + * Retrieves whether the two DDs represent different functions. + * + * @param other The DD that is to be compared with the current one. + * @return True if the DDs represent the different functions. + */ + bool operator!=(Dd<DdType::CUDD> const& other) const; /*! * Adds the two DDs. @@ -44,7 +54,7 @@ namespace storm { * @param other The DD to add to the current one. * @return The result of the addition. */ - Dd<CUDD> operator+(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> operator+(Dd<DdType::CUDD> const& other) const; /*! * Adds the given DD to the current one. @@ -52,7 +62,7 @@ namespace storm { * @param other The DD to add to the current one. * @return A reference to the current DD after the operation. */ - Dd<CUDD>& operator+=(Dd<CUDD> const& other); + Dd<DdType::CUDD>& operator+=(Dd<DdType::CUDD> const& other); /*! * Multiplies the two DDs. @@ -60,7 +70,7 @@ namespace storm { * @param other The DD to multiply with the current one. * @return The result of the multiplication. */ - Dd<CUDD> operator*(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> operator*(Dd<DdType::CUDD> const& other) const; /*! * Multiplies the given DD with the current one and assigns the result to the current DD. @@ -68,7 +78,7 @@ namespace storm { * @param other The DD to multiply with the current one. * @return A reference to the current DD after the operation. */ - Dd<CUDD>& operator*=(Dd<CUDD> const& other); + Dd<DdType::CUDD>& operator*=(Dd<DdType::CUDD> const& other); /*! * Subtracts the given DD from the current one. @@ -76,7 +86,7 @@ namespace storm { * @param other The DD to subtract from the current one. * @return The result of the subtraction. */ - Dd<CUDD> operator-(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> operator-(Dd<DdType::CUDD> const& other) const; /*! * Subtracts the given DD from the current one and assigns the result to the current DD. @@ -84,7 +94,7 @@ namespace storm { * @param other The DD to subtract from the current one. * @return A reference to the current DD after the operation. */ - Dd<CUDD>& operator-=(Dd<CUDD> const& other); + Dd<DdType::CUDD>& operator-=(Dd<DdType::CUDD> const& other); /*! * Divides the current DD by the given one. @@ -92,7 +102,7 @@ namespace storm { * @param other The DD by which to divide the current one. * @return The result of the division. */ - Dd<CUDD> operator/(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> operator/(Dd<DdType::CUDD> const& other) const; /*! * Divides the current DD by the given one and assigns the result to the current DD. @@ -100,14 +110,14 @@ namespace storm { * @param other The DD by which to divide the current one. * @return A reference to the current DD after the operation. */ - Dd<CUDD>& operator/=(Dd<CUDD> const& other); + Dd<DdType::CUDD>& operator/=(Dd<DdType::CUDD> const& other); /*! * Subtracts the DD from the constant zero function. * * @return The resulting function represented as a DD. */ - Dd<CUDD> minus() const; + Dd<DdType::CUDD> minus() const; /*! * Retrieves the logical complement of the current DD. The result will map all encodings with a value @@ -115,7 +125,7 @@ namespace storm { * * @return The logical complement of the current DD. */ - Dd<CUDD> operator~() const; + Dd<DdType::CUDD> operator~() const; /*! * Logically complements the current DD. The result will map all encodings with a value @@ -123,7 +133,7 @@ namespace storm { * * @return A reference to the current DD after the operation. */ - Dd<CUDD>& complement(); + Dd<DdType::CUDD>& complement(); /*! * Retrieves the function that maps all evaluations to one that have an identical function values. @@ -131,7 +141,7 @@ namespace storm { * @param other The DD with which to perform the operation. * @return The resulting function represented as a DD. */ - Dd<CUDD> equals(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> equals(Dd<DdType::CUDD> const& other) const; /*! * Retrieves the function that maps all evaluations to one that have distinct function values. @@ -139,7 +149,7 @@ namespace storm { * @param other The DD with which to perform the operation. * @return The resulting function represented as a DD. */ - Dd<CUDD> notEquals(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> notEquals(Dd<DdType::CUDD> const& other) const; /*! * Retrieves the function that maps all evaluations to one whose function value in the first DD are less @@ -148,7 +158,7 @@ namespace storm { * @param other The DD with which to perform the operation. * @return The resulting function represented as a DD. */ - Dd<CUDD> less(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> less(Dd<DdType::CUDD> const& other) const; /*! * Retrieves the function that maps all evaluations to one whose function value in the first DD are less or @@ -157,7 +167,7 @@ namespace storm { * @param other The DD with which to perform the operation. * @return The resulting function represented as a DD. */ - Dd<CUDD> lessOrEqual(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> lessOrEqual(Dd<DdType::CUDD> const& other) const; /*! * Retrieves the function that maps all evaluations to one whose function value in the first DD are greater @@ -166,7 +176,7 @@ namespace storm { * @param other The DD with which to perform the operation. * @return The resulting function represented as a DD. */ - Dd<CUDD> greater(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> greater(Dd<DdType::CUDD> const& other) const; /*! * Retrieves the function that maps all evaluations to one whose function value in the first DD are greater @@ -175,7 +185,7 @@ namespace storm { * @param other The DD with which to perform the operation. * @return The resulting function represented as a DD. */ - Dd<CUDD> greaterOrEqual(Dd<CUDD> const& other) const; + Dd<DdType::CUDD> greaterOrEqual(Dd<DdType::CUDD> const& other) const; /*! * Existentially abstracts from the given meta variables. @@ -222,7 +232,7 @@ namespace storm { * matrix multiplication. * @return A DD representing the result of the matrix-matrix multiplication. */ - Dd<CUDD> multiplyMatrix(Dd<CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames); + Dd<DdType::CUDD> multiplyMatrix(Dd<DdType::CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames); /*! * Retrieves the number of encodings that are mapped to a non-zero value. @@ -294,7 +304,16 @@ namespace storm { * have. All values must be within the range of the respective meta variable. * @param targetValue The new function value of the modified encodings. */ - void setValue(std::unordered_map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue); + void setValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap = std::map<std::string, int_fast64_t>(), double targetValue = 0); + + /*! + * Retrieves the value of the function when all meta variables are assigned the values of the given mapping. + * Note that the mapping must specify values for all meta variables contained in the DD. + * + * @param metaVariableNameToValueMap A mapping of meta variable names to their values. + * @return The value of the function evaluated with the given input. + */ + double getValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap = std::map<std::string, int_fast64_t>()) const; /*! * Retrieves whether this DD represents the constant one function. @@ -310,6 +329,13 @@ namespace storm { */ bool isZero() const; + /*! + * Retrieves whether this DD represents a constant function. + * + * @return True if this DD represents a constants function. + */ + bool isConstant() const; + /*! * Retrieves whether the given meta variable is contained in the DD. * @@ -345,20 +371,21 @@ namespace storm { * * @param filename The name of the file to which the DD is to be exported. */ - void exportToDot(std::string const& filename) const; + void exportToDot(std::string const& filename = "") const; /*! * Retrieves the manager that is responsible for this DD. * * A pointer to the manager that is responsible for this DD. */ - std::shared_ptr<DdManager<CUDD>> getDdManager() const; + std::shared_ptr<DdManager<DdType::CUDD>> getDdManager() const; + friend std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd); private: /*! - * Retrieves the CUDD ADD object associated with this DD. + * Retrieves a reference to the CUDD ADD object associated with this DD. * - * @return The CUDD ADD object assoicated with this DD. + * @return The CUDD ADD object associated with this DD. */ ADD getCuddAdd(); @@ -390,10 +417,10 @@ namespace storm { * @param cuddAdd The CUDD ADD to store. * @param */ - Dd(std::shared_ptr<DdManager<CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames = std::set<std::string>()); + Dd(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames = std::set<std::string>()); // A pointer to the manager responsible for this DD. - std::shared_ptr<DdManager<CUDD>> ddManager; + std::shared_ptr<DdManager<DdType::CUDD>> ddManager; // The ADD created by CUDD. ADD cuddAdd; diff --git a/src/storage/dd/CuddDdManager.cpp b/src/storage/dd/CuddDdManager.cpp index dd6ce4f4f..9843b5c92 100644 --- a/src/storage/dd/CuddDdManager.cpp +++ b/src/storage/dd/CuddDdManager.cpp @@ -4,34 +4,47 @@ #include "src/storage/dd/CuddDdManager.h" #include "src/exceptions/InvalidArgumentException.h" -#include <iostream> - namespace storm { namespace dd { - DdManager<CUDD>::DdManager() : metaVariableMap(), cuddManager() { + DdManager<DdType::CUDD>::DdManager() : metaVariableMap(), cuddManager() { // Intentionally left empty. } - Dd<CUDD> DdManager<CUDD>::getOne() { - return Dd<CUDD>(this->shared_from_this(), cuddManager.addOne()); + Dd<DdType::CUDD> DdManager<DdType::CUDD>::getOne() { + return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addOne()); } - Dd<CUDD> DdManager<CUDD>::getZero() { - return Dd<CUDD>(this->shared_from_this(), cuddManager.addZero()); + Dd<DdType::CUDD> DdManager<DdType::CUDD>::getZero() { + return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addZero()); } - Dd<CUDD> DdManager<CUDD>::getConstant(double value) { - return Dd<CUDD>(this->shared_from_this(), cuddManager.constant(value)); + Dd<DdType::CUDD> DdManager<DdType::CUDD>::getConstant(double value) { + return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.constant(value)); } - Dd<CUDD> DdManager<CUDD>::getEncoding(std::string const& metaVariableName, int_fast64_t value) { - std::vector<Dd<CUDD>> ddVariables = this->getMetaVariable(metaVariableName).getDdVariables(); + Dd<DdType::CUDD> DdManager<DdType::CUDD>::getEncoding(std::string const& metaVariableName, int_fast64_t value) { + // Check whether the meta variable exists. + if (!this->hasMetaVariable(metaVariableName)) { + throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'."; + } + + DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(metaVariableName); + + // Check whether the value is legal for this meta variable. + if (value < metaVariable.getLow() || value > metaVariable.getHigh()) { + throw storm::exceptions::InvalidArgumentException() << "Illegal value " << value << " for meta variable '" << metaVariableName << "'."; + } + + // Now compute the encoding relative to the low value of the meta variable. + value -= metaVariable.getLow(); + + std::vector<Dd<DdType::CUDD>> const& ddVariables = metaVariable.getDdVariables(); - Dd<CUDD> result; + Dd<DdType::CUDD> result; if (value & (1ull << (ddVariables.size() - 1))) { result = ddVariables[0]; } else { - result = ddVariables[0]; + result = ~ddVariables[0]; } for (std::size_t i = 1; i < ddVariables.size(); ++i) { @@ -41,21 +54,42 @@ namespace storm { result *= ~ddVariables[i]; } } + + return result; + } + + Dd<DdType::CUDD> DdManager<DdType::CUDD>::getRange(std::string const& metaVariableName) { + // Check whether the meta variable exists. + if (!this->hasMetaVariable(metaVariableName)) { + throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'."; + } + + storm::dd::DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(metaVariableName); + + Dd<DdType::CUDD> result = this->getZero(); + for (int_fast64_t value = metaVariable.getLow(); value <= metaVariable.getHigh(); ++value) { + result.setValue(metaVariableName, value, static_cast<double>(1)); + } return result; } - Dd<CUDD> DdManager<CUDD>::getRange(std::string const metaVariableName) { - storm::dd::DdMetaVariable<CUDD> const& metaVariable = this->getMetaVariable(metaVariableName); + Dd<DdType::CUDD> DdManager<DdType::CUDD>::getIdentity(std::string const& metaVariableName) { + // Check whether the meta variable exists. + if (!this->hasMetaVariable(metaVariableName)) { + throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'."; + } + + storm::dd::DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(metaVariableName); - Dd<CUDD> result = this->getZero(); + Dd<DdType::CUDD> result = this->getZero(); for (int_fast64_t value = metaVariable.getLow(); value <= metaVariable.getHigh(); ++value) { - result.setValue(metaVariableName, value - metaVariable.getLow(), static_cast<double>(value)); + result.setValue(metaVariableName, value, static_cast<double>(value)); } return result; } - void DdManager<CUDD>::addMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high) { + void DdManager<DdType::CUDD>::addMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high) { // Check whether a meta variable already exists. if (this->hasMetaVariable(name)) { throw storm::exceptions::InvalidArgumentException() << "A meta variable '" << name << "' already exists."; @@ -68,15 +102,15 @@ namespace storm { std::size_t numberOfBits = static_cast<std::size_t>(std::ceil(std::log2(high - low + 1))); - std::vector<Dd<CUDD>> variables; + std::vector<Dd<DdType::CUDD>> variables; for (std::size_t i = 0; i < numberOfBits; ++i) { - variables.emplace_back(Dd<CUDD>(this->shared_from_this(), cuddManager.addVar(), {name})); + variables.emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addVar(), {name})); } - metaVariableMap.emplace(name, DdMetaVariable<CUDD>(name, low, high, variables, this->shared_from_this())); + metaVariableMap.emplace(name, DdMetaVariable<DdType::CUDD>(name, low, high, variables, this->shared_from_this())); } - void DdManager<CUDD>::addMetaVariablesInterleaved(std::vector<std::string> const& names, int_fast64_t low, int_fast64_t high) { + void DdManager<DdType::CUDD>::addMetaVariablesInterleaved(std::vector<std::string> const& names, int_fast64_t low, int_fast64_t high) { // Make sure that at least one meta variable is added. if (names.size() == 0) { throw storm::exceptions::InvalidArgumentException() << "Illegal to add zero meta variables."; @@ -103,30 +137,30 @@ namespace storm { // Add the variables in interleaved order. std::size_t numberOfBits = static_cast<std::size_t>(std::ceil(std::log2(high - low + 1))); - std::vector<std::vector<Dd<CUDD>>> variables(names.size()); + std::vector<std::vector<Dd<DdType::CUDD>>> variables(names.size()); for (uint_fast64_t bit = 0; bit < numberOfBits; ++bit) { for (uint_fast64_t i = 0; i < names.size(); ++i) { - variables[i].emplace_back(Dd<CUDD>(this->shared_from_this(), cuddManager.addVar(), {names[i]})); + variables[i].emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addVar(), {names[i]})); } } // Now add the meta variables. for (uint_fast64_t i = 0; i < names.size(); ++i) { - metaVariableMap.emplace(names[i], DdMetaVariable<CUDD>(names[i], low, high, variables[i], this->shared_from_this())); + metaVariableMap.emplace(names[i], DdMetaVariable<DdType::CUDD>(names[i], low, high, variables[i], this->shared_from_this())); } } - DdMetaVariable<CUDD> const& DdManager<CUDD>::getMetaVariable(std::string const& metaVariableName) const { + DdMetaVariable<DdType::CUDD> const& DdManager<DdType::CUDD>::getMetaVariable(std::string const& metaVariableName) const { auto const& nameVariablePair = metaVariableMap.find(metaVariableName); if (!this->hasMetaVariable(metaVariableName)) { - throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name."; + throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'."; } return nameVariablePair->second; } - std::set<std::string> DdManager<CUDD>::getAllMetaVariableNames() const { + std::set<std::string> DdManager<DdType::CUDD>::getAllMetaVariableNames() const { std::set<std::string> result; for (auto const& nameValuePair : metaVariableMap) { result.insert(nameValuePair.first); @@ -134,15 +168,15 @@ namespace storm { return result; } - std::size_t DdManager<CUDD>::getNumberOfMetaVariables() const { + std::size_t DdManager<DdType::CUDD>::getNumberOfMetaVariables() const { return this->metaVariableMap.size(); } - bool DdManager<CUDD>::hasMetaVariable(std::string const& metaVariableName) const { + bool DdManager<DdType::CUDD>::hasMetaVariable(std::string const& metaVariableName) const { return this->metaVariableMap.find(metaVariableName) != this->metaVariableMap.end(); } - Cudd& DdManager<CUDD>::getCuddManager() { + Cudd& DdManager<DdType::CUDD>::getCuddManager() { return this->cuddManager; } } diff --git a/src/storage/dd/CuddDdManager.h b/src/storage/dd/CuddDdManager.h index 1d0d32a99..ca3f9c2c3 100644 --- a/src/storage/dd/CuddDdManager.h +++ b/src/storage/dd/CuddDdManager.h @@ -14,10 +14,10 @@ namespace storm { namespace dd { template<> - class DdManager<CUDD> : public std::enable_shared_from_this<DdManager<CUDD>> { + class DdManager<DdType::CUDD> : public std::enable_shared_from_this<DdManager<DdType::CUDD>> { public: // To break the cylic dependencies, we need to forward-declare the other DD-related classes. - friend class Dd<CUDD>; + friend class Dd<DdType::CUDD>; /*! * Creates an empty manager without any meta variables. @@ -25,11 +25,11 @@ namespace storm { DdManager(); // Explictly forbid copying a DdManager, but allow moving it. - DdManager(DdManager<CUDD> const& other) = delete; - DdManager<CUDD>& operator=(DdManager<CUDD> const& other) = delete; + DdManager(DdManager<DdType::CUDD> const& other) = delete; + DdManager<DdType::CUDD>& operator=(DdManager<DdType::CUDD> const& other) = delete; #ifndef WINDOWS - DdManager(DdManager<CUDD>&& other) = default; - DdManager<CUDD>& operator=(DdManager<CUDD>&& other) = default; + DdManager(DdManager<DdType::CUDD>&& other) = default; + DdManager<DdType::CUDD>& operator=(DdManager<DdType::CUDD>&& other) = default; #endif /*! @@ -37,21 +37,21 @@ namespace storm { * * @return A DD representing the constant one function. */ - Dd<CUDD> getOne(); + Dd<DdType::CUDD> getOne(); /*! * Retrieves a DD representing the constant zero function. * * @return A DD representing the constant zero function. */ - Dd<CUDD> getZero(); + Dd<DdType::CUDD> getZero(); /*! * Retrieves a DD representing the constant function with the given value. * * @return A DD representing the constant function with the given value. */ - Dd<CUDD> getConstant(double value); + Dd<DdType::CUDD> getConstant(double value); /*! * Retrieves the DD representing the function that maps all inputs which have the given meta variable equal @@ -62,16 +62,25 @@ namespace storm { * @return The DD representing the function that maps all inputs which have the given meta variable equal * to the given value one. */ - Dd<CUDD> getEncoding(std::string const& metaVariableName, int_fast64_t value); + Dd<DdType::CUDD> getEncoding(std::string const& metaVariableName, int_fast64_t value); /*! * Retrieves the DD representing the range of the meta variable, i.e., a function that maps all legal values * of the range of the meta variable to one. * * @param metaVariableName The name of the meta variable whose range to retrieve. - * @return The range of the meta variable + * @return The range of the meta variable. */ - Dd<CUDD> getRange(std::string const metaVariableName); + Dd<DdType::CUDD> getRange(std::string const& metaVariableName); + + /*! + * Retrieves the DD representing the identity of the meta variable, i.e., a function that maps all legal + * values of the range of the meta variable to themselves. + * + * @param metaVariableName The name of the meta variable whose identity to retrieve. + * @return The identity of the meta variable. + */ + Dd<DdType::CUDD> getIdentity(std::string const& metaVariableName); /*! * Adds a meta variable with the given name and range. @@ -97,7 +106,7 @@ namespace storm { * @param metaVariableName The name of the meta variable to retrieve. * @return The meta variable with the given name. */ - DdMetaVariable<CUDD> const& getMetaVariable(std::string const& metaVariableName) const; + DdMetaVariable<DdType::CUDD> const& getMetaVariable(std::string const& metaVariableName) const; /*! * Retrieves the names of all meta variables that have been added to the manager. @@ -130,7 +139,7 @@ namespace storm { Cudd& getCuddManager(); // A mapping from variable names to the meta variable information. - std::unordered_map<std::string, DdMetaVariable<CUDD>> metaVariableMap; + std::unordered_map<std::string, DdMetaVariable<DdType::CUDD>> metaVariableMap; // The manager responsible for the DDs created/modified with this DdManager. Cudd cuddManager; diff --git a/src/storage/dd/DdMetaVariable.cpp b/src/storage/dd/DdMetaVariable.cpp index 7671289fc..9132eab03 100644 --- a/src/storage/dd/DdMetaVariable.cpp +++ b/src/storage/dd/DdMetaVariable.cpp @@ -47,6 +47,6 @@ namespace storm { } // Explicitly instantiate DdMetaVariable. - template class DdMetaVariable<CUDD>; + template class DdMetaVariable<DdType::CUDD>; } } \ No newline at end of file diff --git a/src/storage/dd/DdType.h b/src/storage/dd/DdType.h index 327832ec5..feb2fe70a 100644 --- a/src/storage/dd/DdType.h +++ b/src/storage/dd/DdType.h @@ -3,7 +3,7 @@ namespace storm { namespace dd { - enum DdType { + enum class DdType { CUDD }; } diff --git a/src/storage/expressions/BaseExpression.cpp b/src/storage/expressions/BaseExpression.cpp new file mode 100644 index 000000000..b9734a9ad --- /dev/null +++ b/src/storage/expressions/BaseExpression.cpp @@ -0,0 +1,65 @@ +#include "src/storage/expressions/BaseExpression.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidTypeException.h" + +namespace storm { + namespace expressions { + BaseExpression::BaseExpression(ExpressionReturnType returnType) : returnType(returnType) { + // Intentionally left empty. + } + + ExpressionReturnType BaseExpression::getReturnType() const { + return this->returnType; + } + + bool BaseExpression::hasIntegralReturnType() const { + return this->getReturnType() == ExpressionReturnType::Int; + } + + bool BaseExpression::hasNumericalReturnType() const { + return this->getReturnType() == ExpressionReturnType::Double || this->getReturnType() == ExpressionReturnType::Int; + } + + bool BaseExpression::hasBooleanReturnType() const { + return this->getReturnType() == ExpressionReturnType::Bool; + } + + int_fast64_t BaseExpression::evaluateAsInt(Valuation const* valuation) const { + LOG_THROW(false, storm::exceptions::InvalidTypeException, "Unable to evaluate expression as integer."); + } + + bool BaseExpression::evaluateAsBool(Valuation const* valuation) const { + LOG_THROW(false, storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean."); + } + + double BaseExpression::evaluateAsDouble(Valuation const* valuation) const { + LOG_THROW(false, storm::exceptions::InvalidTypeException, "Unable to evaluate expression as double."); + } + + bool BaseExpression::isConstant() const { + return false; + } + + bool BaseExpression::isTrue() const { + return false; + } + + bool BaseExpression::isFalse() const { + return false; + } + + std::shared_ptr<BaseExpression const> BaseExpression::getSharedPointer() const { + return this->shared_from_this(); + } + + std::ostream& operator<<(std::ostream& stream, ExpressionReturnType const& enumValue) { + stream << static_cast<std::underlying_type<ExpressionReturnType>::type>(enumValue); + return stream; + } + + std::ostream& operator<<(std::ostream& stream, BaseExpression const& expression) { + expression.printToStream(stream); + return stream; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/BaseExpression.h b/src/storage/expressions/BaseExpression.h new file mode 100644 index 000000000..fb3df4514 --- /dev/null +++ b/src/storage/expressions/BaseExpression.h @@ -0,0 +1,176 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_BASEEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_BASEEXPRESSION_H_ + +#include <cstdint> +#include <memory> +#include <set> +#include <iostream> + +#include "src/storage/expressions/Valuation.h" +#include "src/storage/expressions/ExpressionVisitor.h" +#include "src/exceptions/InvalidArgumentException.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + /*! + * Each node in an expression tree has a uniquely defined type from this enum. + */ + enum class ExpressionReturnType {Undefined, Bool, Int, Double}; + + std::ostream& operator<<(std::ostream& stream, ExpressionReturnType const& enumValue); + + /*! + * The base class of all expression classes. + */ + class BaseExpression : public std::enable_shared_from_this<BaseExpression> { + public: + /*! + * Constructs a base expression with the given return type. + * + * @param returnType The return type of the expression. + */ + BaseExpression(ExpressionReturnType returnType); + + // Create default versions of constructors and assignments. + BaseExpression(BaseExpression const&) = default; + BaseExpression& operator=(BaseExpression const&) = default; +#ifndef WINDOWS + BaseExpression(BaseExpression&&) = default; + BaseExpression& operator=(BaseExpression&&) = default; +#endif + + // Make the destructor virtual (to allow destruction via base class pointer) and default it. + virtual ~BaseExpression() = default; + + /*! + * Evaluates the expression under the valuation of unknowns (variables and constants) given by the + * valuation and returns the resulting boolean value. If the return type of the expression is not a boolean + * an exception is thrown. + * + * @param valuation The valuation of unknowns under which to evaluate the expression. + * @return The boolean value of the expression under the given valuation. + */ + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const; + + /*! + * Evaluates the expression under the valuation of unknowns (variables and constants) given by the + * valuation and returns the resulting integer value. If the return type of the expression is not an integer + * an exception is thrown. + * + * @param valuation The valuation of unknowns under which to evaluate the expression. + * @return The integer value of the expression under the given valuation. + */ + virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const; + + /*! + * Evaluates the expression under the valuation of unknowns (variables and constants) given by the + * valuation and returns the resulting double value. If the return type of the expression is not a double + * an exception is thrown. + * + * @param valuation The valuation of unknowns under which to evaluate the expression. + * @return The double value of the expression under the given valuation. + */ + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const; + + /*! + * Retrieves whether the expression is constant, i.e., contains no variables or undefined constants. + * + * @return True iff the expression is constant. + */ + virtual bool isConstant() const; + + /*! + * Checks if the expression is equal to the boolean literal true. + * + * @return True iff the expression is equal to the boolean literal true. + */ + virtual bool isTrue() const; + + /*! + * Checks if the expression is equal to the boolean literal false. + * + * @return True iff the expression is equal to the boolean literal false. + */ + virtual bool isFalse() const; + + /*! + * Retrieves the set of all variables that appear in the expression. + * + * @return The set of all variables that appear in the expression. + */ + virtual std::set<std::string> getVariables() const = 0; + + /*! + * Retrieves the set of all constants that appear in the expression. + * + * @return The set of all constants that appear in the expression. + */ + virtual std::set<std::string> getConstants() const = 0; + + /*! + * Simplifies the expression according to some simple rules. + * + * @return A pointer to the simplified expression. + */ + virtual std::shared_ptr<BaseExpression const> simplify() const = 0; + + /*! + * Accepts the given visitor by calling its visit method. + * + * @param visitor The visitor that is to be accepted. + */ + virtual void accept(ExpressionVisitor* visitor) const = 0; + + /*! + * Retrieves whether the expression has a numerical return type, i.e., integer or double. + * + * @return True iff the expression has a numerical return type. + */ + bool hasNumericalReturnType() const; + + /*! + * Retrieves whether the expression has an integral return type, i.e., integer. + * + * @return True iff the expression has an integral return type. + */ + bool hasIntegralReturnType() const; + + /*! + * Retrieves whether the expression has a boolean return type. + * + * @return True iff the expression has a boolean return type. + */ + bool hasBooleanReturnType() const; + + /*! + * Retrieves a shared pointer to this expression. + * + * @return A shared pointer to this expression. + */ + std::shared_ptr<BaseExpression const> getSharedPointer() const; + + /*! + * Retrieves the return type of the expression. + * + * @return The return type of the expression. + */ + ExpressionReturnType getReturnType() const; + + friend std::ostream& operator<<(std::ostream& stream, BaseExpression const& expression); + protected: + /*! + * Prints the expression to the given stream. + * + * @param stream The stream to which to write the expression. + */ + virtual void printToStream(std::ostream& stream) const = 0; + + private: + // The return type of this expression. + ExpressionReturnType returnType; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_BASEEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/BinaryBooleanFunctionExpression.cpp b/src/storage/expressions/BinaryBooleanFunctionExpression.cpp new file mode 100644 index 000000000..9f5e5edeb --- /dev/null +++ b/src/storage/expressions/BinaryBooleanFunctionExpression.cpp @@ -0,0 +1,97 @@ +#include "src/storage/expressions/BinaryBooleanFunctionExpression.h" +#include "src/storage/expressions/BooleanLiteralExpression.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidTypeException.h" + +namespace storm { + namespace expressions { + BinaryBooleanFunctionExpression::BinaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType) : BinaryExpression(returnType, firstOperand, secondOperand), operatorType(operatorType) { + // Intentionally left empty. + } + + BinaryBooleanFunctionExpression::OperatorType BinaryBooleanFunctionExpression::getOperatorType() const { + return this->operatorType; + } + + bool BinaryBooleanFunctionExpression::evaluateAsBool(Valuation const* valuation) const { + LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean."); + + bool firstOperandEvaluation = this->getFirstOperand()->evaluateAsBool(valuation); + bool secondOperandEvaluation = this->getSecondOperand()->evaluateAsBool(valuation); + + bool result; + switch (this->getOperatorType()) { + case OperatorType::And: result = firstOperandEvaluation && secondOperandEvaluation; break; + case OperatorType::Or: result = firstOperandEvaluation || secondOperandEvaluation; break; + case OperatorType::Implies: result = !firstOperandEvaluation || secondOperandEvaluation; break; + case OperatorType::Iff: result = (firstOperandEvaluation && secondOperandEvaluation) || (!firstOperandEvaluation && !secondOperandEvaluation); break; + } + + return result; + } + + std::shared_ptr<BaseExpression const> BinaryBooleanFunctionExpression::simplify() const { + std::shared_ptr<BaseExpression const> firstOperandSimplified = this->getFirstOperand()->simplify(); + std::shared_ptr<BaseExpression const> secondOperandSimplified = this->getSecondOperand()->simplify(); + + switch (this->getOperatorType()) { + case OperatorType::And: if (firstOperandSimplified->isTrue()) { + return secondOperandSimplified; + } else if (firstOperandSimplified->isFalse()) { + return firstOperandSimplified; + } else if (secondOperandSimplified->isTrue()) { + return firstOperandSimplified; + } else if (secondOperandSimplified->isFalse()) { + return secondOperandSimplified; + } + break; + case OperatorType::Or: if (firstOperandSimplified->isTrue()) { + return firstOperandSimplified; + } else if (firstOperandSimplified->isFalse()) { + return secondOperandSimplified; + } else if (secondOperandSimplified->isTrue()) { + return secondOperandSimplified; + } else if (secondOperandSimplified->isFalse()) { + return firstOperandSimplified; + } + break; + case OperatorType::Implies: if (firstOperandSimplified->isTrue()) { + return secondOperandSimplified; + } else if (firstOperandSimplified->isFalse()) { + return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true)); + } else if (secondOperandSimplified->isTrue()) { + return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true)); + } + break; + case OperatorType::Iff: if (firstOperandSimplified->isTrue() && secondOperandSimplified->isTrue()) { + return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true)); + } else if (firstOperandSimplified->isFalse() && secondOperandSimplified->isFalse()) { + return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true)); + } + break; + } + + // If the two successors remain unchanged, we can return a shared_ptr to this very object. + if (firstOperandSimplified.get() == this->getFirstOperand().get() && secondOperandSimplified.get() == this->getSecondOperand().get()) { + return this->shared_from_this(); + } else { + return std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(this->getReturnType(), firstOperandSimplified, secondOperandSimplified, this->getOperatorType())); + } + } + + void BinaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + void BinaryBooleanFunctionExpression::printToStream(std::ostream& stream) const { + stream << "(" << *this->getFirstOperand(); + switch (this->getOperatorType()) { + case OperatorType::And: stream << " & "; break; + case OperatorType::Or: stream << " | "; break; + case OperatorType::Implies: stream << " => "; break; + case OperatorType::Iff: stream << " <=> "; break; + } + stream << *this->getSecondOperand() << ")"; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/BinaryBooleanFunctionExpression.h b/src/storage/expressions/BinaryBooleanFunctionExpression.h new file mode 100644 index 000000000..7a05a1ab5 --- /dev/null +++ b/src/storage/expressions/BinaryBooleanFunctionExpression.h @@ -0,0 +1,58 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ + +#include "src/storage/expressions/BinaryExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class BinaryBooleanFunctionExpression : public BinaryExpression { + public: + /*! + * An enum type specifying the different operators applicable. + */ + enum class OperatorType {And, Or, Implies, Iff}; + + /*! + * Creates a binary boolean function expression with the given return type, operands and operator. + * + * @param returnType The return type of the expression. + * @param firstOperand The first operand of the expression. + * @param secondOperand The second operand of the expression. + * @param functionType The operator of the expression. + */ + BinaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType); + + // Instantiate constructors and assignments with their default implementations. + BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression const& other) = default; + BinaryBooleanFunctionExpression& operator=(BinaryBooleanFunctionExpression const& other) = default; +#ifndef WINDOWS + BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression&&) = default; + BinaryBooleanFunctionExpression& operator=(BinaryBooleanFunctionExpression&&) = default; +#endif + virtual ~BinaryBooleanFunctionExpression() = default; + + // Override base class methods. + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the operator associated with the expression. + * + * @return The operator associated with the expression. + */ + OperatorType getOperatorType() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The operator of the expression. + OperatorType operatorType; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/BinaryExpression.cpp b/src/storage/expressions/BinaryExpression.cpp new file mode 100644 index 000000000..cfd18447c --- /dev/null +++ b/src/storage/expressions/BinaryExpression.cpp @@ -0,0 +1,35 @@ +#include "src/storage/expressions/BinaryExpression.h" + +namespace storm { + namespace expressions { + BinaryExpression::BinaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand) : BaseExpression(returnType), firstOperand(firstOperand), secondOperand(secondOperand) { + // Intentionally left empty. + } + + bool BinaryExpression::isConstant() const { + return this->getFirstOperand()->isConstant() && this->getSecondOperand()->isConstant(); + } + + std::set<std::string> BinaryExpression::getVariables() const { + std::set<std::string> firstVariableSet = this->getFirstOperand()->getVariables(); + std::set<std::string> secondVariableSet = this->getSecondOperand()->getVariables(); + firstVariableSet.insert(secondVariableSet.begin(), secondVariableSet.end()); + return firstVariableSet; + } + + std::set<std::string> BinaryExpression::getConstants() const { + std::set<std::string> firstConstantSet = this->getFirstOperand()->getVariables(); + std::set<std::string> secondConstantSet = this->getSecondOperand()->getVariables(); + firstConstantSet.insert(secondConstantSet.begin(), secondConstantSet.end()); + return firstConstantSet; + } + + std::shared_ptr<BaseExpression const> const& BinaryExpression::getFirstOperand() const { + return this->firstOperand; + } + + std::shared_ptr<BaseExpression const> const& BinaryExpression::getSecondOperand() const { + return this->secondOperand; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/BinaryExpression.h b/src/storage/expressions/BinaryExpression.h new file mode 100644 index 000000000..640297a91 --- /dev/null +++ b/src/storage/expressions/BinaryExpression.h @@ -0,0 +1,61 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_BINARYEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_BINARYEXPRESSION_H_ + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + /*! + * The base class of all binary expressions. + */ + class BinaryExpression : public BaseExpression { + public: + /*! + * Constructs a binary expression with the given return type and operands. + * + * @param returnType The return type of the expression. + * @param firstOperand The first operand of the expression. + * @param secondOperand The second operand of the expression. + */ + BinaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand); + + // Instantiate constructors and assignments with their default implementations. + BinaryExpression(BinaryExpression const& other) = default; + BinaryExpression& operator=(BinaryExpression const& other) = default; +#ifndef WINDOWS + BinaryExpression(BinaryExpression&&) = default; + BinaryExpression& operator=(BinaryExpression&&) = default; +#endif + virtual ~BinaryExpression() = default; + + // Override base class methods. + virtual bool isConstant() const override; + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + + /*! + * Retrieves the first operand of the expression. + * + * @return The first operand of the expression. + */ + std::shared_ptr<BaseExpression const> const& getFirstOperand() const; + + /*! + * Retrieves the second operand of the expression. + * + * @return The second operand of the expression. + */ + std::shared_ptr<BaseExpression const> const& getSecondOperand() const; + + private: + // The first operand of the expression. + std::shared_ptr<BaseExpression const> firstOperand; + + // The second operand of the expression. + std::shared_ptr<BaseExpression const> secondOperand; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_BINARYEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/BinaryNumericalFunctionExpression.cpp b/src/storage/expressions/BinaryNumericalFunctionExpression.cpp new file mode 100644 index 000000000..225bea963 --- /dev/null +++ b/src/storage/expressions/BinaryNumericalFunctionExpression.cpp @@ -0,0 +1,75 @@ +#include <algorithm> + +#include "src/storage/expressions/BinaryNumericalFunctionExpression.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidTypeException.h" + +namespace storm { + namespace expressions { + BinaryNumericalFunctionExpression::BinaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType) : BinaryExpression(returnType, firstOperand, secondOperand), operatorType(operatorType) { + // Intentionally left empty. + } + + BinaryNumericalFunctionExpression::OperatorType BinaryNumericalFunctionExpression::getOperatorType() const { + return this->operatorType; + } + + int_fast64_t BinaryNumericalFunctionExpression::evaluateAsInt(Valuation const* valuation) const { + LOG_THROW(this->hasIntegralReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as integer."); + + int_fast64_t firstOperandEvaluation = this->getFirstOperand()->evaluateAsInt(valuation); + int_fast64_t secondOperandEvaluation = this->getSecondOperand()->evaluateAsInt(valuation); + switch (this->getOperatorType()) { + case OperatorType::Plus: return firstOperandEvaluation + secondOperandEvaluation; break; + case OperatorType::Minus: return firstOperandEvaluation - secondOperandEvaluation; break; + case OperatorType::Times: return firstOperandEvaluation * secondOperandEvaluation; break; + case OperatorType::Divide: return firstOperandEvaluation / secondOperandEvaluation; break; + case OperatorType::Min: return std::min(firstOperandEvaluation, secondOperandEvaluation); break; + case OperatorType::Max: return std::max(firstOperandEvaluation, secondOperandEvaluation); break; + } + } + + double BinaryNumericalFunctionExpression::evaluateAsDouble(Valuation const* valuation) const { + LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as double."); + + double firstOperandEvaluation = this->getFirstOperand()->evaluateAsDouble(valuation); + double secondOperandEvaluation = this->getSecondOperand()->evaluateAsDouble(valuation); + switch (this->getOperatorType()) { + case OperatorType::Plus: return static_cast<double>(firstOperandEvaluation + secondOperandEvaluation); break; + case OperatorType::Minus: return static_cast<double>(firstOperandEvaluation - secondOperandEvaluation); break; + case OperatorType::Times: return static_cast<double>(firstOperandEvaluation * secondOperandEvaluation); break; + case OperatorType::Divide: return static_cast<double>(firstOperandEvaluation / secondOperandEvaluation); break; + case OperatorType::Min: return static_cast<double>(std::min(firstOperandEvaluation, secondOperandEvaluation)); break; + case OperatorType::Max: return static_cast<double>(std::max(firstOperandEvaluation, secondOperandEvaluation)); break; + } + } + + std::shared_ptr<BaseExpression const> BinaryNumericalFunctionExpression::simplify() const { + std::shared_ptr<BaseExpression const> firstOperandSimplified = this->getFirstOperand()->simplify(); + std::shared_ptr<BaseExpression const> secondOperandSimplified = this->getSecondOperand()->simplify(); + + if (firstOperandSimplified.get() == this->getFirstOperand().get() && secondOperandSimplified.get() == this->getSecondOperand().get()) { + return this->shared_from_this(); + } else { + return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType(), firstOperandSimplified, secondOperandSimplified, this->getOperatorType())); + } + } + + void BinaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + void BinaryNumericalFunctionExpression::printToStream(std::ostream& stream) const { + stream << "("; + switch (this->getOperatorType()) { + case OperatorType::Plus: stream << *this->getFirstOperand() << " + " << *this->getSecondOperand(); break; + case OperatorType::Minus: stream << *this->getFirstOperand() << " - " << *this->getSecondOperand(); break; + case OperatorType::Times: stream << *this->getFirstOperand() << " * " << *this->getSecondOperand(); break; + case OperatorType::Divide: stream << *this->getFirstOperand() << " / " << *this->getSecondOperand(); break; + case OperatorType::Min: stream << "min(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break; + case OperatorType::Max: stream << "max(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break; + } + stream << ")"; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/BinaryNumericalFunctionExpression.h b/src/storage/expressions/BinaryNumericalFunctionExpression.h new file mode 100644 index 000000000..4e8573a4c --- /dev/null +++ b/src/storage/expressions/BinaryNumericalFunctionExpression.h @@ -0,0 +1,59 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_BINARYNUMERICALFUNCTIONEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_BINARYNUMERICALFUNCTIONEXPRESSION_H_ + +#include "src/storage/expressions/BinaryExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class BinaryNumericalFunctionExpression : public BinaryExpression { + public: + /*! + * An enum type specifying the different operators applicable. + */ + enum class OperatorType {Plus, Minus, Times, Divide, Min, Max}; + + /*! + * Constructs a binary numerical function expression with the given return type, operands and operator. + * + * @param returnType The return type of the expression. + * @param firstOperand The first operand of the expression. + * @param secondOperand The second operand of the expression. + * @param functionType The operator of the expression. + */ + BinaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType); + + // Instantiate constructors and assignments with their default implementations. + BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression const& other) = default; + BinaryNumericalFunctionExpression& operator=(BinaryNumericalFunctionExpression const& other) = default; +#ifndef WINDOWS + BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression&&) = default; + BinaryNumericalFunctionExpression& operator=(BinaryNumericalFunctionExpression&&) = default; +#endif + virtual ~BinaryNumericalFunctionExpression() = default; + + // Override base class methods. + virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override; + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the operator associated with the expression. + * + * @return The operator associated with the expression. + */ + OperatorType getOperatorType() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The operator of the expression. + OperatorType operatorType; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_BINARYNUMERICALFUNCTIONEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/BinaryRelationExpression.cpp b/src/storage/expressions/BinaryRelationExpression.cpp new file mode 100644 index 000000000..7e48c2286 --- /dev/null +++ b/src/storage/expressions/BinaryRelationExpression.cpp @@ -0,0 +1,59 @@ +#include "src/storage/expressions/BinaryRelationExpression.h" + +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidTypeException.h" + +namespace storm { + namespace expressions { + BinaryRelationExpression::BinaryRelationExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, RelationType relationType) : BinaryExpression(returnType, firstOperand, secondOperand), relationType(relationType) { + // Intentionally left empty. + } + + bool BinaryRelationExpression::evaluateAsBool(Valuation const* valuation) const { + LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean."); + + double firstOperandEvaluated = this->getFirstOperand()->evaluateAsDouble(valuation); + double secondOperandEvaluated = this->getSecondOperand()->evaluateAsDouble(valuation); + switch (this->getRelationType()) { + case RelationType::Equal: return firstOperandEvaluated == secondOperandEvaluated; break; + case RelationType::NotEqual: return firstOperandEvaluated != secondOperandEvaluated; break; + case RelationType::Greater: return firstOperandEvaluated > secondOperandEvaluated; break; + case RelationType::GreaterOrEqual: return firstOperandEvaluated >= secondOperandEvaluated; break; + case RelationType::Less: return firstOperandEvaluated < secondOperandEvaluated; break; + case RelationType::LessOrEqual: return firstOperandEvaluated <= secondOperandEvaluated; break; + } + } + + std::shared_ptr<BaseExpression const> BinaryRelationExpression::simplify() const { + std::shared_ptr<BaseExpression const> firstOperandSimplified = this->getFirstOperand()->simplify(); + std::shared_ptr<BaseExpression const> secondOperandSimplified = this->getSecondOperand()->simplify(); + + if (firstOperandSimplified.get() == this->getFirstOperand().get() && secondOperandSimplified.get() == this->getSecondOperand().get()) { + return this->shared_from_this(); + } else { + return std::shared_ptr<BaseExpression>(new BinaryRelationExpression(this->getReturnType(), firstOperandSimplified, secondOperandSimplified, this->getRelationType())); + } + } + + void BinaryRelationExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + BinaryRelationExpression::RelationType BinaryRelationExpression::getRelationType() const { + return this->relationType; + } + + void BinaryRelationExpression::printToStream(std::ostream& stream) const { + stream << "(" << *this->getFirstOperand(); + switch (this->getRelationType()) { + case RelationType::Equal: stream << " = "; break; + case RelationType::NotEqual: stream << " != "; break; + case RelationType::Greater: stream << " > "; break; + case RelationType::GreaterOrEqual: stream << " >= "; break; + case RelationType::Less: stream << " < "; break; + case RelationType::LessOrEqual: stream << " <= "; break; + } + stream << *this->getSecondOperand() << ")"; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/BinaryRelationExpression.h b/src/storage/expressions/BinaryRelationExpression.h new file mode 100644 index 000000000..b88ef71f9 --- /dev/null +++ b/src/storage/expressions/BinaryRelationExpression.h @@ -0,0 +1,58 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ + +#include "src/storage/expressions/BinaryExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class BinaryRelationExpression : public BinaryExpression { + public: + /*! + * An enum type specifying the different relations applicable. + */ + enum class RelationType {Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual}; + + /*! + * Creates a binary relation expression with the given return type, operands and relation type. + * + * @param returnType The return type of the expression. + * @param firstOperand The first operand of the expression. + * @param secondOperand The second operand of the expression. + * @param relationType The operator of the expression. + */ + BinaryRelationExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, RelationType relationType); + + // Instantiate constructors and assignments with their default implementations. + BinaryRelationExpression(BinaryRelationExpression const& other) = default; + BinaryRelationExpression& operator=(BinaryRelationExpression const& other) = default; +#ifndef WINDOWS + BinaryRelationExpression(BinaryRelationExpression&&) = default; + BinaryRelationExpression& operator=(BinaryRelationExpression&&) = default; +#endif + virtual ~BinaryRelationExpression() = default; + + // Override base class methods. + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the relation associated with the expression. + * + * @return The relation associated with the expression. + */ + RelationType getRelationType() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The relation type of the expression. + RelationType relationType; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/BooleanConstantExpression.cpp b/src/storage/expressions/BooleanConstantExpression.cpp new file mode 100644 index 000000000..de87dab48 --- /dev/null +++ b/src/storage/expressions/BooleanConstantExpression.cpp @@ -0,0 +1,23 @@ +#include "src/storage/expressions/BooleanConstantExpression.h" +#include "src/exceptions/ExceptionMacros.h" + +namespace storm { + namespace expressions { + BooleanConstantExpression::BooleanConstantExpression(std::string const& constantName) : ConstantExpression(ExpressionReturnType::Bool, constantName) { + // Intentionally left empty. + } + + bool BooleanConstantExpression::evaluateAsBool(Valuation const* valuation) const { + LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation."); + return valuation->getBooleanValue(this->getConstantName()); + } + + void BooleanConstantExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + std::shared_ptr<BaseExpression const> BooleanConstantExpression::simplify() const { + return this->shared_from_this(); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/BooleanConstantExpression.h b/src/storage/expressions/BooleanConstantExpression.h new file mode 100644 index 000000000..dd204d7a5 --- /dev/null +++ b/src/storage/expressions/BooleanConstantExpression.h @@ -0,0 +1,35 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ + +#include "src/storage/expressions/ConstantExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class BooleanConstantExpression : public ConstantExpression { + public: + /*! + * Creates a boolean constant expression with the given constant name. + * + * @param constantName The name of the boolean constant associated with this expression. + */ + BooleanConstantExpression(std::string const& constantName); + + // Instantiate constructors and assignments with their default implementations. + BooleanConstantExpression(BooleanConstantExpression const& other) = default; + BooleanConstantExpression& operator=(BooleanConstantExpression const& other) = default; +#ifndef WINDOWS + BooleanConstantExpression(BooleanConstantExpression&&) = default; + BooleanConstantExpression& operator=(BooleanConstantExpression&&) = default; +#endif + virtual ~BooleanConstantExpression() = default; + + // Override base class methods. + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override; + virtual void accept(ExpressionVisitor* visitor) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ */ diff --git a/src/storage/expressions/BooleanLiteralExpression.cpp b/src/storage/expressions/BooleanLiteralExpression.cpp new file mode 100644 index 000000000..6ef15fe83 --- /dev/null +++ b/src/storage/expressions/BooleanLiteralExpression.cpp @@ -0,0 +1,49 @@ +#include "src/storage/expressions/BooleanLiteralExpression.h" + +namespace storm { + namespace expressions { + BooleanLiteralExpression::BooleanLiteralExpression(bool value) : BaseExpression(ExpressionReturnType::Bool), value(value) { + // Intentionally left empty. + } + + bool BooleanLiteralExpression::evaluateAsBool(Valuation const* valuation) const { + return this->getValue(); + } + + bool BooleanLiteralExpression::isConstant() const { + return true; + } + + bool BooleanLiteralExpression::isTrue() const { + return this->getValue() == true; + } + + bool BooleanLiteralExpression::isFalse() const { + return this->getValue() == false; + } + + std::set<std::string> BooleanLiteralExpression::getVariables() const { + return std::set<std::string>(); + } + + std::set<std::string> BooleanLiteralExpression::getConstants() const { + return std::set<std::string>(); + } + + std::shared_ptr<BaseExpression const> BooleanLiteralExpression::simplify() const { + return this->shared_from_this(); + } + + void BooleanLiteralExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + bool BooleanLiteralExpression::getValue() const { + return this->value; + } + + void BooleanLiteralExpression::printToStream(std::ostream& stream) const { + stream << (this->getValue() ? "true" : "false"); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/BooleanLiteralExpression.h b/src/storage/expressions/BooleanLiteralExpression.h new file mode 100644 index 000000000..6c0413236 --- /dev/null +++ b/src/storage/expressions/BooleanLiteralExpression.h @@ -0,0 +1,55 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class BooleanLiteralExpression : public BaseExpression { + public: + /*! + * Creates a boolean literal expression with the given value. + * + * @param value The value of the boolean literal. + */ + BooleanLiteralExpression(bool value); + + // Instantiate constructors and assignments with their default implementations. + BooleanLiteralExpression(BooleanLiteralExpression const& other) = default; + BooleanLiteralExpression& operator=(BooleanLiteralExpression const& other) = default; +#ifndef WINDOWS + BooleanLiteralExpression(BooleanLiteralExpression&&) = default; + BooleanLiteralExpression& operator=(BooleanLiteralExpression&&) = default; +#endif + virtual ~BooleanLiteralExpression() = default; + + // Override base class methods. + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override; + virtual bool isConstant() const override; + virtual bool isTrue() const override; + virtual bool isFalse() const override; + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the value of the boolean literal. + * + * @return The value of the boolean literal. + */ + bool getValue() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The value of the boolean literal. + bool value; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/ConstantExpression.cpp b/src/storage/expressions/ConstantExpression.cpp new file mode 100644 index 000000000..d09a75573 --- /dev/null +++ b/src/storage/expressions/ConstantExpression.cpp @@ -0,0 +1,25 @@ +#include "src/storage/expressions/ConstantExpression.h" + +namespace storm { + namespace expressions { + ConstantExpression::ConstantExpression(ExpressionReturnType returnType, std::string const& constantName) : BaseExpression(returnType), constantName(constantName) { + // Intentionally left empty. + } + + std::set<std::string> ConstantExpression::getVariables() const { + return std::set<std::string>(); + } + + std::set<std::string> ConstantExpression::getConstants() const { + return {this->getConstantName()}; + } + + std::string const& ConstantExpression::getConstantName() const { + return this->constantName; + } + + void ConstantExpression::printToStream(std::ostream& stream) const { + stream << this->getConstantName(); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/ConstantExpression.h b/src/storage/expressions/ConstantExpression.h new file mode 100644 index 000000000..50f00c235 --- /dev/null +++ b/src/storage/expressions/ConstantExpression.h @@ -0,0 +1,50 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_CONSTANTEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_CONSTANTEXPRESSION_H_ + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class ConstantExpression : public BaseExpression { + public: + /*! + * Creates a constant expression with the given return type and constant name. + * + * @param returnType The return type of the expression. + * @param constantName The name of the constant associated with this expression. + */ + ConstantExpression(ExpressionReturnType returnType, std::string const& constantName); + + // Instantiate constructors and assignments with their default implementations. + ConstantExpression(ConstantExpression const& other) = default; + ConstantExpression& operator=(ConstantExpression const& other) = default; +#ifndef WINDOWS + ConstantExpression(ConstantExpression&&) = default; + ConstantExpression& operator=(ConstantExpression&&) = default; +#endif + virtual ~ConstantExpression() = default; + + // Override base class methods. + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + + /*! + * Retrieves the name of the constant. + * + * @return The name of the constant. + */ + std::string const& getConstantName() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The name of the constant. + std::string constantName; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_CONSTANTEXPRESSION_H_ */ diff --git a/src/storage/expressions/DoubleConstantExpression.cpp b/src/storage/expressions/DoubleConstantExpression.cpp new file mode 100644 index 000000000..e7d541975 --- /dev/null +++ b/src/storage/expressions/DoubleConstantExpression.cpp @@ -0,0 +1,23 @@ +#include "src/storage/expressions/DoubleConstantExpression.h" +#include "src/exceptions/ExceptionMacros.h" + +namespace storm { + namespace expressions { + DoubleConstantExpression::DoubleConstantExpression(std::string const& constantName) : ConstantExpression(ExpressionReturnType::Double, constantName) { + // Intentionally left empty. + } + + double DoubleConstantExpression::evaluateAsDouble(Valuation const* valuation) const { + LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation."); + return valuation->getDoubleValue(this->getConstantName()); + } + + std::shared_ptr<BaseExpression const> DoubleConstantExpression::simplify() const { + return this->shared_from_this(); + } + + void DoubleConstantExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/DoubleConstantExpression.h b/src/storage/expressions/DoubleConstantExpression.h new file mode 100644 index 000000000..b271bf6db --- /dev/null +++ b/src/storage/expressions/DoubleConstantExpression.h @@ -0,0 +1,35 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ + +#include "src/storage/expressions/ConstantExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class DoubleConstantExpression : public ConstantExpression { + public: + /*! + * Creates a double constant expression with the given constant name. + * + * @param constantName The name of the double constant associated with this expression. + */ + DoubleConstantExpression(std::string const& constantName); + + // Instantiate constructors and assignments with their default implementations. + DoubleConstantExpression(DoubleConstantExpression const& other) = default; + DoubleConstantExpression& operator=(DoubleConstantExpression const& other) = default; +#ifndef WINDOWS + DoubleConstantExpression(DoubleConstantExpression&&) = default; + DoubleConstantExpression& operator=(DoubleConstantExpression&&) = default; +#endif + virtual ~DoubleConstantExpression() = default; + + // Override base class methods. + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual void accept(ExpressionVisitor* visitor) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ */ diff --git a/src/storage/expressions/DoubleLiteralExpression.cpp b/src/storage/expressions/DoubleLiteralExpression.cpp new file mode 100644 index 000000000..642a1817f --- /dev/null +++ b/src/storage/expressions/DoubleLiteralExpression.cpp @@ -0,0 +1,41 @@ +#include "src/storage/expressions/DoubleLiteralExpression.h" + +namespace storm { + namespace expressions { + DoubleLiteralExpression::DoubleLiteralExpression(double value) : BaseExpression(ExpressionReturnType::Double), value(value) { + // Intentionally left empty. + } + + double DoubleLiteralExpression::evaluateAsDouble(Valuation const* valuation) const { + return this->getValue(); + } + + bool DoubleLiteralExpression::isConstant() const { + return true; + } + + std::set<std::string> DoubleLiteralExpression::getVariables() const { + return std::set<std::string>(); + } + + std::set<std::string> DoubleLiteralExpression::getConstants() const { + return std::set<std::string>(); + } + + std::shared_ptr<BaseExpression const> DoubleLiteralExpression::simplify() const { + return this->shared_from_this(); + } + + void DoubleLiteralExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + double DoubleLiteralExpression::getValue() const { + return this->value; + } + + void DoubleLiteralExpression::printToStream(std::ostream& stream) const { + stream << this->getValue(); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/DoubleLiteralExpression.h b/src/storage/expressions/DoubleLiteralExpression.h new file mode 100644 index 000000000..e4bc28b81 --- /dev/null +++ b/src/storage/expressions/DoubleLiteralExpression.h @@ -0,0 +1,53 @@ +#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 value The value of the double literal. + */ + DoubleLiteralExpression(double value); + + // Instantiate constructors and assignments with their default implementations. + DoubleLiteralExpression(DoubleLiteralExpression const& other) = default; + DoubleLiteralExpression& operator=(DoubleLiteralExpression const& other) = default; +#ifndef WINDOWS + DoubleLiteralExpression(DoubleLiteralExpression&&) = default; + DoubleLiteralExpression& operator=(DoubleLiteralExpression&&) = default; +#endif + virtual ~DoubleLiteralExpression() = default; + + // Override base class methods. + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual bool isConstant() const override; + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void 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_ */ \ No newline at end of file diff --git a/src/storage/expressions/Expression.cpp b/src/storage/expressions/Expression.cpp new file mode 100644 index 000000000..7eb94966b --- /dev/null +++ b/src/storage/expressions/Expression.cpp @@ -0,0 +1,260 @@ +#include <map> +#include <unordered_map> + +#include "src/storage/expressions/Expression.h" +#include "src/storage/expressions/SubstitutionVisitor.h" +#include "src/storage/expressions/IdentifierSubstitutionVisitor.h" +#include "src/exceptions/InvalidTypeException.h" +#include "src/exceptions/ExceptionMacros.h" + +#include "src/storage/expressions/IfThenElseExpression.h" +#include "src/storage/expressions/BinaryBooleanFunctionExpression.h" +#include "src/storage/expressions/BinaryNumericalFunctionExpression.h" +#include "src/storage/expressions/BinaryRelationExpression.h" +#include "src/storage/expressions/BooleanConstantExpression.h" +#include "src/storage/expressions/IntegerConstantExpression.h" +#include "src/storage/expressions/DoubleConstantExpression.h" +#include "src/storage/expressions/BooleanLiteralExpression.h" +#include "src/storage/expressions/IntegerLiteralExpression.h" +#include "src/storage/expressions/DoubleLiteralExpression.h" +#include "src/storage/expressions/VariableExpression.h" +#include "src/storage/expressions/UnaryBooleanFunctionExpression.h" +#include "src/storage/expressions/UnaryNumericalFunctionExpression.h" + +namespace storm { + namespace expressions { + Expression::Expression(std::shared_ptr<BaseExpression const> const& expressionPtr) : expressionPtr(expressionPtr) { + // Intentionally left empty. + } + + template<template<typename... Arguments> class MapType> + Expression Expression::substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const { + return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(this->getBaseExpressionPointer().get()); + } + + template<template<typename... Arguments> class MapType> + Expression Expression::substitute(MapType<std::string, std::string> const& identifierToIdentifierMap) const { + return IdentifierSubstitutionVisitor<MapType>(identifierToIdentifierMap).substitute(this->getBaseExpressionPointer().get()); + } + + bool Expression::evaluateAsBool(Valuation const* valuation) const { + return this->getBaseExpression().evaluateAsBool(valuation); + } + + int_fast64_t Expression::evaluateAsInt(Valuation const* valuation) const { + return this->getBaseExpression().evaluateAsInt(valuation); + } + + double Expression::evaluateAsDouble(Valuation const* valuation) const { + return this->getBaseExpression().evaluateAsDouble(valuation); + } + + Expression Expression::simplify() { + return Expression(this->getBaseExpression().simplify()); + } + + bool Expression::isConstant() const { + return this->getBaseExpression().isConstant(); + } + + bool Expression::isTrue() const { + return this->getBaseExpression().isTrue(); + } + + bool Expression::isFalse() const { + return this->getBaseExpression().isFalse(); + } + + std::set<std::string> Expression::getVariables() const { + return this->getBaseExpression().getVariables(); + } + + std::set<std::string> Expression::getConstants() const { + return this->getBaseExpression().getConstants(); + } + + BaseExpression const& Expression::getBaseExpression() const { + return *this->expressionPtr; + } + + std::shared_ptr<BaseExpression const> const& Expression::getBaseExpressionPointer() const { + return this->expressionPtr; + } + + ExpressionReturnType Expression::getReturnType() const { + return this->getBaseExpression().getReturnType(); + } + + bool Expression::hasNumericalReturnType() const { + return this->getReturnType() == ExpressionReturnType::Int || this->getReturnType() == ExpressionReturnType::Double; + } + + bool Expression::hasBooleanReturnType() const { + return this->getReturnType() == ExpressionReturnType::Bool; + } + + Expression Expression::createBooleanLiteral(bool value) { + return Expression(std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(value))); + } + + Expression Expression::createTrue() { + return createBooleanLiteral(true); + } + + Expression Expression::createFalse() { + return createBooleanLiteral(false); + } + + Expression Expression::createIntegerLiteral(int_fast64_t value) { + return Expression(std::shared_ptr<BaseExpression>(new IntegerLiteralExpression(value))); + } + + Expression Expression::createDoubleLiteral(double value) { + return Expression(std::shared_ptr<BaseExpression>(new DoubleLiteralExpression(value))); + } + + Expression Expression::createBooleanVariable(std::string const& variableName) { + return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Bool, variableName))); + } + + Expression Expression::createIntegerVariable(std::string const& variableName) { + return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Int, variableName))); + } + + Expression Expression::createDoubleVariable(std::string const& variableName) { + return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Double, variableName))); + } + + Expression Expression::createUndefinedVariable(std::string const& variableName) { + return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Undefined, variableName))); + } + + Expression Expression::createBooleanConstant(std::string const& constantName) { + return Expression(std::shared_ptr<BaseExpression>(new BooleanConstantExpression(constantName))); + } + + Expression Expression::createIntegerConstant(std::string const& constantName) { + return Expression(std::shared_ptr<BaseExpression>(new IntegerConstantExpression(constantName))); + } + + Expression Expression::createDoubleConstant(std::string const& constantName) { + return Expression(std::shared_ptr<BaseExpression>(new DoubleConstantExpression(constantName))); + } + + Expression Expression::operator+(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '+' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Plus))); + } + + Expression Expression::operator-(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '-' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Minus))); + } + + Expression Expression::operator-() const { + LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '-' requires numerical operand."); + return Expression(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getReturnType(), this->getBaseExpressionPointer(), UnaryNumericalFunctionExpression::OperatorType::Minus))); + } + + Expression Expression::operator*(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '*' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Times))); + } + + Expression Expression::operator/(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '/' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Divide))); + } + + Expression Expression::operator&&(Expression const& other) const { + LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '&&' requires boolean operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::And))); + } + + Expression Expression::operator||(Expression const& other) const { + LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '||' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Or))); + } + + Expression Expression::operator!() const { + LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '!' requires boolean operand."); + return Expression(std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), UnaryBooleanFunctionExpression::OperatorType::Not))); + } + + Expression Expression::operator==(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '==' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::Equal))); + } + + Expression Expression::operator!=(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '!=' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::NotEqual))); + } + + Expression Expression::operator>(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '>' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::Greater))); + } + + Expression Expression::operator>=(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '>=' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::GreaterOrEqual))); + } + + Expression Expression::operator<(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '<' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::Less))); + } + + Expression Expression::operator<=(Expression const& other) const { + LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '<=' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::LessOrEqual))); + } + + Expression Expression::minimum(Expression const& lhs, Expression const& rhs) { + LOG_THROW(lhs.hasNumericalReturnType() && rhs.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'min' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(lhs.getReturnType() == ExpressionReturnType::Int && rhs.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, lhs.getBaseExpressionPointer(), rhs.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Min))); + } + + Expression Expression::maximum(Expression const& lhs, Expression const& rhs) { + LOG_THROW(lhs.hasNumericalReturnType() && rhs.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'max' requires numerical operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(lhs.getReturnType() == ExpressionReturnType::Int && rhs.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, lhs.getBaseExpressionPointer(), rhs.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Max))); + } + + Expression Expression::ite(Expression const& thenExpression, Expression const& elseExpression) { + LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Condition of if-then-else operator must be of boolean type."); + LOG_THROW(thenExpression.hasBooleanReturnType() && elseExpression.hasBooleanReturnType() || thenExpression.hasNumericalReturnType() && elseExpression.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "'then' and 'else' expression of if-then-else operator must have equal return type."); + return Expression(std::shared_ptr<BaseExpression>(new IfThenElseExpression(thenExpression.hasBooleanReturnType() && elseExpression.hasBooleanReturnType() ? ExpressionReturnType::Bool : (thenExpression.getReturnType() == ExpressionReturnType::Int && elseExpression.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double), this->getBaseExpressionPointer(), thenExpression.getBaseExpressionPointer(), elseExpression.getBaseExpressionPointer()))); + } + + Expression Expression::implies(Expression const& other) const { + LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '&&' requires boolean operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Implies))); + } + + Expression Expression::iff(Expression const& other) const { + LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '&&' requires boolean operands."); + return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Iff))); + } + + Expression Expression::floor() const { + LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'floor' requires numerical operand."); + return Expression(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(ExpressionReturnType::Int, this->getBaseExpressionPointer(), UnaryNumericalFunctionExpression::OperatorType::Floor))); + } + + Expression Expression::ceil() const { + LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'ceil' requires numerical operand."); + return Expression(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(ExpressionReturnType::Int, this->getBaseExpressionPointer(), UnaryNumericalFunctionExpression::OperatorType::Ceil))); + } + + template Expression Expression::substitute<std::map>(std::map<std::string, storm::expressions::Expression> const&) const; + template Expression Expression::substitute<std::unordered_map>(std::unordered_map<std::string, storm::expressions::Expression> const&) const; + template Expression Expression::substitute<std::map>(std::map<std::string, std::string> const&) const; + template Expression Expression::substitute<std::unordered_map>(std::unordered_map<std::string, std::string> const&) const; + + std::ostream& operator<<(std::ostream& stream, Expression const& expression) { + stream << expression.getBaseExpression(); + return stream; + } + } +} diff --git a/src/storage/expressions/Expression.h b/src/storage/expressions/Expression.h new file mode 100644 index 000000000..ea7d99572 --- /dev/null +++ b/src/storage/expressions/Expression.h @@ -0,0 +1,209 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_ + +#include <memory> + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class Expression { + public: + Expression() = default; + + /*! + * Creates an expression with the given underlying base expression. + * + * @param expressionPtr A pointer to the underlying base expression. + */ + Expression(std::shared_ptr<BaseExpression const> const& expressionPtr); + + // Instantiate constructors and assignments with their default implementations. + Expression(Expression const& other) = default; + Expression& operator=(Expression const& other) = default; +#ifndef WINDOWS + Expression(Expression&&) = default; + Expression& operator=(Expression&&) = default; +#endif + + // Static factory methods to create atomic expression parts. + static Expression createBooleanLiteral(bool value); + static Expression createTrue(); + static Expression createFalse(); + static Expression createIntegerLiteral(int_fast64_t value); + static Expression createDoubleLiteral(double value); + static Expression createBooleanVariable(std::string const& variableName); + static Expression createIntegerVariable(std::string const& variableName); + static Expression createDoubleVariable(std::string const& variableName); + static Expression createUndefinedVariable(std::string const& variableName); + static Expression createBooleanConstant(std::string const& constantName); + static Expression createIntegerConstant(std::string const& constantName); + static Expression createDoubleConstant(std::string const& constantName); + + // Provide operator overloads to conveniently construct new expressions from other expressions. + Expression operator+(Expression const& other) const; + Expression operator-(Expression const& other) const; + Expression operator-() const; + Expression operator*(Expression const& other) const; + Expression operator/(Expression const& other) const; + Expression operator&&(Expression const& other) const; + Expression operator||(Expression const& other) const; + Expression operator!() const; + Expression operator==(Expression const& other) const; + Expression operator!=(Expression const& other) const; + Expression operator>(Expression const& other) const; + Expression operator>=(Expression const& other) const; + Expression operator<(Expression const& other) const; + Expression operator<=(Expression const& other) const; + + Expression ite(Expression const& thenExpression, Expression const& elseExpression); + Expression implies(Expression const& other) const; + Expression iff(Expression const& other) const; + + Expression floor() const; + Expression ceil() const; + + static Expression minimum(Expression const& lhs, Expression const& rhs); + static Expression maximum(Expression const& lhs, Expression const& rhs); + + /*! + * Substitutes all occurrences of identifiers according to the given map. Note that this substitution is + * done simultaneously, i.e., identifiers appearing in the expressions that were "plugged in" are not + * substituted. + * + * @param identifierToExpressionMap A mapping from identifiers to the expression they are substituted with. + * @return An expression in which all identifiers in the key set of the mapping are replaced by the + * expression they are mapped to. + */ + template<template<typename... Arguments> class MapType> + Expression substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const; + + /*! + * Substitutes all occurrences of identifiers with different names given by a mapping. + * + * @param identifierToIdentifierMap A mapping from identifiers to identifiers they are substituted with. + * @return An expression in which all identifiers in the key set of the mapping are replaced by the + * identifiers they are mapped to. + */ + template<template<typename... Arguments> class MapType> + Expression substitute(MapType<std::string, std::string> const& identifierToIdentifierMap) const; + + /*! + * Evaluates the expression under the valuation of unknowns (variables and constants) given by the + * valuation and returns the resulting boolean value. If the return type of the expression is not a boolean + * an exception is thrown. + * + * @param valuation The valuation of unknowns under which to evaluate the expression. + * @return The boolean value of the expression under the given valuation. + */ + bool evaluateAsBool(Valuation const* valuation = nullptr) const; + + /*! + * Evaluates the expression under the valuation of unknowns (variables and constants) given by the + * valuation and returns the resulting integer value. If the return type of the expression is not an integer + * an exception is thrown. + * + * @param valuation The valuation of unknowns under which to evaluate the expression. + * @return The integer value of the expression under the given valuation. + */ + int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const; + + /*! + * Evaluates the expression under the valuation of unknowns (variables and constants) given by the + * valuation and returns the resulting double value. If the return type of the expression is not a double + * an exception is thrown. + * + * @param valuation The valuation of unknowns under which to evaluate the expression. + * @return The double value of the expression under the given valuation. + */ + double evaluateAsDouble(Valuation const* valuation = nullptr) const; + + /*! + * Simplifies the expression according to some basic rules. + * + * @return The simplified expression. + */ + Expression simplify(); + + /*! + * Retrieves whether the expression is constant, i.e., contains no variables or undefined constants. + * + * @return True iff the expression is constant. + */ + bool isConstant() const; + + /*! + * Checks if the expression is equal to the boolean literal true. + * + * @return True iff the expression is equal to the boolean literal true. + */ + bool isTrue() const; + + /*! + * Checks if the expression is equal to the boolean literal false. + * + * @return True iff the expression is equal to the boolean literal false. + */ + bool isFalse() const; + + /*! + * Retrieves the set of all variables that appear in the expression. + * + * @return The set of all variables that appear in the expression. + */ + std::set<std::string> getVariables() const; + + /*! + * Retrieves the set of all constants that appear in the expression. + * + * @return The set of all constants that appear in the expression. + */ + std::set<std::string> getConstants() const; + + /*! + * Retrieves the base expression underlying this expression object. Note that prior to calling this, the + * expression object must be properly initialized. + * + * @return A reference to the underlying base expression. + */ + BaseExpression const& getBaseExpression() const; + + /*! + * Retrieves a pointer to the base expression underlying this expression object. + * + * @return A pointer to the underlying base expression. + */ + std::shared_ptr<BaseExpression const> const& getBaseExpressionPointer() const; + + /*! + * Retrieves the return type of the expression. + * + * @return The return type of the expression. + */ + ExpressionReturnType getReturnType() const; + + /*! + * Retrieves whether the expression has a numerical return type, i.e., integer or double. + * + * @return True iff the expression has a numerical return type. + */ + bool hasNumericalReturnType() const; + + /*! + * Retrieves whether the expression has a boolean return type. + * + * @return True iff the expression has a boolean return type. + */ + bool hasBooleanReturnType() const; + + friend std::ostream& operator<<(std::ostream& stream, Expression const& expression); + + private: + // A pointer to the underlying base expression. + std::shared_ptr<BaseExpression const> expressionPtr; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/ExpressionVisitor.h b/src/storage/expressions/ExpressionVisitor.h new file mode 100644 index 000000000..928e6297c --- /dev/null +++ b/src/storage/expressions/ExpressionVisitor.h @@ -0,0 +1,41 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_EXPRESSIONVISITOR_H_ +#define STORM_STORAGE_EXPRESSIONS_EXPRESSIONVISITOR_H_ + +namespace storm { + namespace expressions { + // Forward-declare all expression classes. + class IfThenElseExpression; + class BinaryBooleanFunctionExpression; + class BinaryNumericalFunctionExpression; + class BinaryRelationExpression; + class BooleanConstantExpression; + class DoubleConstantExpression; + class IntegerConstantExpression; + class IntegerConstantExpression; + class VariableExpression; + class UnaryBooleanFunctionExpression; + class UnaryNumericalFunctionExpression; + class BooleanLiteralExpression; + class IntegerLiteralExpression; + class DoubleLiteralExpression; + + class ExpressionVisitor { + public: + virtual void visit(IfThenElseExpression const* expression) = 0; + virtual void visit(BinaryBooleanFunctionExpression const* expression) = 0; + virtual void visit(BinaryNumericalFunctionExpression const* expression) = 0; + virtual void visit(BinaryRelationExpression const* expression) = 0; + virtual void visit(BooleanConstantExpression const* expression) = 0; + virtual void visit(DoubleConstantExpression const* expression) = 0; + virtual void visit(IntegerConstantExpression const* expression) = 0; + virtual void visit(VariableExpression const* expression) = 0; + virtual void visit(UnaryBooleanFunctionExpression const* expression) = 0; + virtual void visit(UnaryNumericalFunctionExpression const* expression) = 0; + virtual void visit(BooleanLiteralExpression const* expression) = 0; + virtual void visit(IntegerLiteralExpression const* expression) = 0; + virtual void visit(DoubleLiteralExpression const* expression) = 0; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_EXPRESSIONVISITOR_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/Expressions.h b/src/storage/expressions/Expressions.h new file mode 100644 index 000000000..df8bbd8ed --- /dev/null +++ b/src/storage/expressions/Expressions.h @@ -0,0 +1,14 @@ +#include "src/storage/expressions/IfThenElseExpression.h" +#include "src/storage/expressions/BinaryBooleanFunctionExpression.h" +#include "src/storage/expressions/BinaryNumericalFunctionExpression.h" +#include "src/storage/expressions/BinaryRelationExpression.h" +#include "src/storage/expressions/BooleanConstantExpression.h" +#include "src/storage/expressions/BooleanLiteralExpression.h" +#include "src/storage/expressions/DoubleConstantExpression.h" +#include "src/storage/expressions/DoubleLiteralExpression.h" +#include "src/storage/expressions/IntegerConstantExpression.h" +#include "src/storage/expressions/IntegerLiteralExpression.h" +#include "src/storage/expressions/UnaryBooleanFunctionExpression.h" +#include "src/storage/expressions/UnaryNumericalFunctionExpression.h" +#include "src/storage/expressions/VariableExpression.h" +#include "src/storage/expressions/Expression.h" \ No newline at end of file diff --git a/src/storage/expressions/IdentifierSubstitutionVisitor.cpp b/src/storage/expressions/IdentifierSubstitutionVisitor.cpp new file mode 100644 index 000000000..17161775a --- /dev/null +++ b/src/storage/expressions/IdentifierSubstitutionVisitor.cpp @@ -0,0 +1,200 @@ +#include <map> +#include <unordered_map> + +#include "src/storage/expressions/IdentifierSubstitutionVisitor.h" + +#include "src/storage/expressions/IfThenElseExpression.h" +#include "src/storage/expressions/BinaryBooleanFunctionExpression.h" +#include "src/storage/expressions/BinaryNumericalFunctionExpression.h" +#include "src/storage/expressions/BinaryRelationExpression.h" +#include "src/storage/expressions/BooleanConstantExpression.h" +#include "src/storage/expressions/IntegerConstantExpression.h" +#include "src/storage/expressions/DoubleConstantExpression.h" +#include "src/storage/expressions/BooleanLiteralExpression.h" +#include "src/storage/expressions/IntegerLiteralExpression.h" +#include "src/storage/expressions/DoubleLiteralExpression.h" +#include "src/storage/expressions/VariableExpression.h" +#include "src/storage/expressions/UnaryBooleanFunctionExpression.h" +#include "src/storage/expressions/UnaryNumericalFunctionExpression.h" + +namespace storm { + namespace expressions { + template<template<typename... Arguments> class MapType> + IdentifierSubstitutionVisitor<MapType>::IdentifierSubstitutionVisitor(MapType<std::string, std::string> const& identifierToIdentifierMap) : identifierToIdentifierMap(identifierToIdentifierMap) { + // Intentionally left empty. + } + + template<template<typename... Arguments> class MapType> + Expression IdentifierSubstitutionVisitor<MapType>::substitute(BaseExpression const* expression) { + expression->accept(this); + return Expression(this->expressionStack.top()); + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(IfThenElseExpression const* expression) { + expression->getCondition()->accept(this); + std::shared_ptr<BaseExpression const> conditionExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getThenExpression()->accept(this); + std::shared_ptr<BaseExpression const> thenExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getElseExpression()->accept(this); + std::shared_ptr<BaseExpression const> elseExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (conditionExpression.get() == expression->getCondition().get() && thenExpression.get() == expression->getThenExpression().get() && elseExpression.get() == expression->getElseExpression().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new IfThenElseExpression(expression->getReturnType(), conditionExpression, thenExpression, elseExpression))); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(BinaryBooleanFunctionExpression const* expression) { + expression->getFirstOperand()->accept(this); + std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getSecondOperand()->accept(this); + std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(BinaryNumericalFunctionExpression const* expression) { + expression->getFirstOperand()->accept(this); + std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getSecondOperand()->accept(this); + std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(BinaryRelationExpression const* expression) { + expression->getFirstOperand()->accept(this); + std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getSecondOperand()->accept(this); + std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getRelationType()))); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(BooleanConstantExpression const* expression) { + // If the boolean constant is in the key set of the substitution, we need to replace it. + auto const& namePair = this->identifierToIdentifierMap.find(expression->getConstantName()); + if (namePair != this->identifierToIdentifierMap.end()) { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new BooleanConstantExpression(namePair->second))); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(DoubleConstantExpression const* expression) { + // If the double constant is in the key set of the substitution, we need to replace it. + auto const& namePair = this->identifierToIdentifierMap.find(expression->getConstantName()); + if (namePair != this->identifierToIdentifierMap.end()) { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new DoubleConstantExpression(namePair->second))); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(IntegerConstantExpression const* expression) { + // If the integer constant is in the key set of the substitution, we need to replace it. + auto const& namePair = this->identifierToIdentifierMap.find(expression->getConstantName()); + if (namePair != this->identifierToIdentifierMap.end()) { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new IntegerConstantExpression(namePair->second))); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(VariableExpression const* expression) { + // If the variable is in the key set of the substitution, we need to replace it. + auto const& namePair = this->identifierToIdentifierMap.find(expression->getVariableName()); + if (namePair != this->identifierToIdentifierMap.end()) { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new VariableExpression(expression->getReturnType(), namePair->second))); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(UnaryBooleanFunctionExpression const* expression) { + expression->getOperand()->accept(this); + std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top(); + expressionStack.pop(); + + // If the argument did not change, we simply push the expression itself. + if (operandExpression.get() == expression->getOperand().get()) { + expressionStack.push(expression->getSharedPointer()); + } else { + expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(UnaryNumericalFunctionExpression const* expression) { + expression->getOperand()->accept(this); + std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top(); + expressionStack.pop(); + + // If the argument did not change, we simply push the expression itself. + if (operandExpression.get() == expression->getOperand().get()) { + expressionStack.push(expression->getSharedPointer()); + } else { + expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(BooleanLiteralExpression const* expression) { + this->expressionStack.push(expression->getSharedPointer()); + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(IntegerLiteralExpression const* expression) { + this->expressionStack.push(expression->getSharedPointer()); + } + + template<template<typename... Arguments> class MapType> + void IdentifierSubstitutionVisitor<MapType>::visit(DoubleLiteralExpression const* expression) { + this->expressionStack.push(expression->getSharedPointer()); + } + + // Explicitly instantiate the class with map and unordered_map. + template class IdentifierSubstitutionVisitor<std::map>; + template class IdentifierSubstitutionVisitor<std::unordered_map>; + } +} diff --git a/src/storage/expressions/IdentifierSubstitutionVisitor.h b/src/storage/expressions/IdentifierSubstitutionVisitor.h new file mode 100644 index 000000000..6be7aa9ca --- /dev/null +++ b/src/storage/expressions/IdentifierSubstitutionVisitor.h @@ -0,0 +1,55 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_IDENTIFIERSUBSTITUTIONVISITOR_H_ +#define STORM_STORAGE_EXPRESSIONS_IDENTIFIERSUBSTITUTIONVISITOR_H_ + +#include <stack> + +#include "src/storage/expressions/Expression.h" +#include "src/storage/expressions/ExpressionVisitor.h" + +namespace storm { + namespace expressions { + template<template<typename... Arguments> class MapType> + class IdentifierSubstitutionVisitor : public ExpressionVisitor { + public: + /*! + * Creates a new substitution visitor that uses the given map to replace identifiers. + * + * @param identifierToExpressionMap A mapping from identifiers to expressions. + */ + IdentifierSubstitutionVisitor(MapType<std::string, std::string> const& identifierToExpressionMap); + + /*! + * Substitutes the identifiers in the given expression according to the previously given map and returns the + * resulting expression. + * + * @param expression The expression in which to substitute the identifiers. + * @return The expression in which all identifiers in the key set of the previously given mapping are + * substituted with the mapped-to expressions. + */ + Expression substitute(BaseExpression const* expression); + + virtual void visit(IfThenElseExpression const* expression) override; + virtual void visit(BinaryBooleanFunctionExpression const* expression) override; + virtual void visit(BinaryNumericalFunctionExpression const* expression) override; + virtual void visit(BinaryRelationExpression const* expression) override; + virtual void visit(BooleanConstantExpression const* expression) override; + virtual void visit(DoubleConstantExpression const* expression) override; + virtual void visit(IntegerConstantExpression const* expression) override; + virtual void visit(VariableExpression const* expression) override; + virtual void visit(UnaryBooleanFunctionExpression const* expression) override; + virtual void visit(UnaryNumericalFunctionExpression const* expression) override; + virtual void visit(BooleanLiteralExpression const* expression) override; + virtual void visit(IntegerLiteralExpression const* expression) override; + virtual void visit(DoubleLiteralExpression const* expression) override; + + private: + // A stack of expression used to pass the results to the higher levels. + std::stack<std::shared_ptr<BaseExpression const>> expressionStack; + + // A mapping of identifier names to expressions with which they shall be replaced. + MapType<std::string, std::string> const& identifierToIdentifierMap; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_IDENTIFIERSUBSTITUTIONVISITOR_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/IfThenElseExpression.cpp b/src/storage/expressions/IfThenElseExpression.cpp new file mode 100644 index 000000000..81ebca670 --- /dev/null +++ b/src/storage/expressions/IfThenElseExpression.cpp @@ -0,0 +1,96 @@ +#include "src/storage/expressions/IfThenElseExpression.h" + +namespace storm { + namespace expressions { + IfThenElseExpression::IfThenElseExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& condition, std::shared_ptr<BaseExpression const> const& thenExpression, std::shared_ptr<BaseExpression const> const& elseExpression) : BaseExpression(returnType), condition(condition), thenExpression(thenExpression), elseExpression(elseExpression) { + // Intentionally left empty. + } + + bool IfThenElseExpression::evaluateAsBool(Valuation const* valuation) const { + bool conditionValue = this->condition->evaluateAsBool(valuation); + if (conditionValue) { + return this->thenExpression->evaluateAsBool(valuation); + } else { + return this->elseExpression->evaluateAsBool(valuation); + } + } + + int_fast64_t IfThenElseExpression::evaluateAsInt(Valuation const* valuation) const { + bool conditionValue = this->condition->evaluateAsBool(valuation); + if (conditionValue) { + return this->thenExpression->evaluateAsInt(valuation); + } else { + return this->elseExpression->evaluateAsInt(valuation); + } + } + + double IfThenElseExpression::evaluateAsDouble(Valuation const* valuation) const { + bool conditionValue = this->condition->evaluateAsBool(valuation); + if (conditionValue) { + return this->thenExpression->evaluateAsDouble(valuation); + } else { + return this->elseExpression->evaluateAsDouble(valuation); + } + } + + bool IfThenElseExpression::isConstant() const { + return this->condition->isConstant() && this->thenExpression->isConstant() && this->elseExpression->isConstant(); + } + + std::set<std::string> IfThenElseExpression::getVariables() const { + std::set<std::string> result = this->condition->getVariables(); + std::set<std::string> tmp = this->thenExpression->getVariables(); + result.insert(tmp.begin(), tmp.end()); + tmp = this->elseExpression->getVariables(); + result.insert(tmp.begin(), tmp.end()); + return result; + } + + std::set<std::string> IfThenElseExpression::getConstants() const { + std::set<std::string> result = this->condition->getConstants(); + std::set<std::string> tmp = this->thenExpression->getConstants(); + result.insert(tmp.begin(), tmp.end()); + tmp = this->elseExpression->getConstants(); + result.insert(tmp.begin(), tmp.end()); + return result; + } + + std::shared_ptr<BaseExpression const> IfThenElseExpression::simplify() const { + std::shared_ptr<BaseExpression const> conditionSimplified; + if (conditionSimplified->isTrue()) { + return this->thenExpression->simplify(); + } else if (conditionSimplified->isFalse()) { + return this->elseExpression->simplify(); + } else { + std::shared_ptr<BaseExpression const> thenExpressionSimplified = this->thenExpression->simplify(); + std::shared_ptr<BaseExpression const> elseExpressionSimplified = this->elseExpression->simplify(); + + if (conditionSimplified.get() == this->condition.get() && thenExpressionSimplified.get() == this->thenExpression.get() && elseExpressionSimplified.get() == this->elseExpression.get()) { + return this->shared_from_this(); + } else { + return std::shared_ptr<BaseExpression>(new IfThenElseExpression(this->getReturnType(), conditionSimplified, thenExpressionSimplified, elseExpressionSimplified)); + } + } + } + + void IfThenElseExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + std::shared_ptr<BaseExpression const> IfThenElseExpression::getCondition() const { + return this->condition; + } + + std::shared_ptr<BaseExpression const> IfThenElseExpression::getThenExpression() const { + return this->thenExpression; + } + + std::shared_ptr<BaseExpression const> IfThenElseExpression::getElseExpression() const { + return this->elseExpression; + } + + void IfThenElseExpression::printToStream(std::ostream& stream) const { + stream << "(" << *this->condition << " ? " << *this->thenExpression << " : " << *this->elseExpression << ")"; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/IfThenElseExpression.h b/src/storage/expressions/IfThenElseExpression.h new file mode 100644 index 000000000..979cb08f0 --- /dev/null +++ b/src/storage/expressions/IfThenElseExpression.h @@ -0,0 +1,77 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_ + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class IfThenElseExpression : public BaseExpression { + public: + /*! + * Creates an if-then-else expression with the given return type, condition and operands. + * + * @param returnType The return type of the expression. + * @param thenExpression The expression evaluated if the condition evaluates true. + * @param elseExpression The expression evaluated if the condition evaluates false. + */ + IfThenElseExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& condition, std::shared_ptr<BaseExpression const> const& thenExpression, std::shared_ptr<BaseExpression const> const& elseExpression); + + // Instantiate constructors and assignments with their default implementations. + IfThenElseExpression(IfThenElseExpression const& other) = default; + IfThenElseExpression& operator=(IfThenElseExpression const& other) = default; +#ifndef WINDOWS + IfThenElseExpression(IfThenElseExpression&&) = default; + IfThenElseExpression& operator=(IfThenElseExpression&&) = default; +#endif + virtual ~IfThenElseExpression() = default; + + // Override base class methods. + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override; + virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override; + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual bool isConstant() const override; + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the condition expression of the if-then-else expression. + * + * @return The condition expression of the if-then-else expression. + */ + std::shared_ptr<BaseExpression const> getCondition() const; + + /*! + * Retrieves the then expression of the if-then-else expression. + * + * @return The then expression of the if-then-else expression. + */ + std::shared_ptr<BaseExpression const> getThenExpression() const; + + /*! + * Retrieves the else expression of the if-then-else expression. + * + * @return The else expression of the if-then-else expression. + */ + std::shared_ptr<BaseExpression const> getElseExpression() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The condition of the if-then-else. + std::shared_ptr<BaseExpression const> condition; + + // The return expression of the if-part. + std::shared_ptr<BaseExpression const> thenExpression; + + // The return expression of the else-part. + std::shared_ptr<BaseExpression const> elseExpression; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/IntegerConstantExpression.cpp b/src/storage/expressions/IntegerConstantExpression.cpp new file mode 100644 index 000000000..60ad8de89 --- /dev/null +++ b/src/storage/expressions/IntegerConstantExpression.cpp @@ -0,0 +1,27 @@ +#include "src/storage/expressions/IntegerConstantExpression.h" +#include "src/exceptions/ExceptionMacros.h" + +namespace storm { + namespace expressions { + IntegerConstantExpression::IntegerConstantExpression(std::string const& constantName) : ConstantExpression(ExpressionReturnType::Int, constantName) { + // Intentionally left empty. + } + + int_fast64_t IntegerConstantExpression::evaluateAsInt(Valuation const* valuation) const { + LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation."); + return valuation->getIntegerValue(this->getConstantName()); + } + + double IntegerConstantExpression::evaluateAsDouble(Valuation const* valuation) const { + return static_cast<double>(this->evaluateAsInt(valuation)); + } + + std::shared_ptr<BaseExpression const> IntegerConstantExpression::simplify() const { + return this->shared_from_this(); + } + + void IntegerConstantExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/IntegerConstantExpression.h b/src/storage/expressions/IntegerConstantExpression.h new file mode 100644 index 000000000..fcf151ead --- /dev/null +++ b/src/storage/expressions/IntegerConstantExpression.h @@ -0,0 +1,36 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ + +#include "src/storage/expressions/ConstantExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class IntegerConstantExpression : public ConstantExpression { + public: + /*! + * Creates an integer constant expression with the given constant name. + * + * @param constantName The name of the integer constant associated with this expression. + */ + IntegerConstantExpression(std::string const& constantName); + + // Instantiate constructors and assignments with their default implementations. + IntegerConstantExpression(IntegerConstantExpression const& other) = default; + IntegerConstantExpression& operator=(IntegerConstantExpression const& other) = default; +#ifndef WINDOWS + IntegerConstantExpression(IntegerConstantExpression&&) = default; + IntegerConstantExpression& operator=(IntegerConstantExpression&&) = default; +#endif + virtual ~IntegerConstantExpression() = default; + + // Override base class methods. + virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override; + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ */ diff --git a/src/storage/expressions/IntegerLiteralExpression.cpp b/src/storage/expressions/IntegerLiteralExpression.cpp new file mode 100644 index 000000000..5e6404fc8 --- /dev/null +++ b/src/storage/expressions/IntegerLiteralExpression.cpp @@ -0,0 +1,45 @@ +#include "src/storage/expressions/IntegerLiteralExpression.h" + +namespace storm { + namespace expressions { + IntegerLiteralExpression::IntegerLiteralExpression(int_fast64_t value) : BaseExpression(ExpressionReturnType::Int), value(value) { + // Intentionally left empty. + } + + int_fast64_t IntegerLiteralExpression::evaluateAsInt(Valuation const* valuation) const { + return this->getValue(); + } + + double IntegerLiteralExpression::evaluateAsDouble(Valuation const* valuation) const { + return static_cast<double>(this->evaluateAsInt(valuation)); + } + + bool IntegerLiteralExpression::isConstant() const { + return true; + } + + std::set<std::string> IntegerLiteralExpression::getVariables() const { + return std::set<std::string>(); + } + + std::set<std::string> IntegerLiteralExpression::getConstants() const { + return std::set<std::string>(); + } + + std::shared_ptr<BaseExpression const> IntegerLiteralExpression::simplify() const { + return this->shared_from_this(); + } + + void IntegerLiteralExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + int_fast64_t IntegerLiteralExpression::getValue() const { + return this->value; + } + + void IntegerLiteralExpression::printToStream(std::ostream& stream) const { + stream << this->getValue(); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/IntegerLiteralExpression.h b/src/storage/expressions/IntegerLiteralExpression.h new file mode 100644 index 000000000..8d50fe688 --- /dev/null +++ b/src/storage/expressions/IntegerLiteralExpression.h @@ -0,0 +1,54 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class IntegerLiteralExpression : public BaseExpression { + public: + /*! + * Creates an integer literal expression with the given value. + * + * @param value The value of the integer literal. + */ + IntegerLiteralExpression(int_fast64_t value); + + // Instantiate constructors and assignments with their default implementations. + IntegerLiteralExpression(IntegerLiteralExpression const& other) = default; + IntegerLiteralExpression& operator=(IntegerLiteralExpression const& other) = default; +#ifndef WINDOWS + IntegerLiteralExpression(IntegerLiteralExpression&&) = default; + IntegerLiteralExpression& operator=(IntegerLiteralExpression&&) = default; +#endif + virtual ~IntegerLiteralExpression() = default; + + // Override base class methods. + virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override; + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual bool isConstant() const override; + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the value of the integer literal. + * + * @return The value of the integer literal. + */ + int_fast64_t getValue() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The value of the integer literal. + int_fast64_t value; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/SimpleValuation.cpp b/src/storage/expressions/SimpleValuation.cpp new file mode 100644 index 000000000..fb6f0088c --- /dev/null +++ b/src/storage/expressions/SimpleValuation.cpp @@ -0,0 +1,120 @@ +#include "src/storage/expressions/SimpleValuation.h" + +#include <boost/functional/hash.hpp> + +namespace storm { + namespace expressions { + SimpleValuation::SimpleValuation() : booleanIdentifierToIndexMap(new std::unordered_map<std::string, uint_fast64_t>()), integerIdentifierToIndexMap(new std::unordered_map<std::string, uint_fast64_t>()), doubleIdentifierToIndexMap(new std::unordered_map<std::string, uint_fast64_t>()), booleanValues(), integerValues(), doubleValues() { + // Intentionally left empty. + } + + bool SimpleValuation::operator==(SimpleValuation const& other) const { + return this->booleanIdentifierToIndexMap.get() == other.booleanIdentifierToIndexMap.get() && this->integerIdentifierToIndexMap.get() == other.integerIdentifierToIndexMap.get() && this->doubleIdentifierToIndexMap.get() == other.doubleIdentifierToIndexMap.get() && this->booleanValues == other.booleanValues && this->integerValues == other.integerValues && this->doubleValues == other.doubleValues; + } + + void SimpleValuation::addBooleanIdentifier(std::string const& name, bool initialValue) { + this->booleanIdentifierToIndexMap->emplace(name, this->booleanValues.size()); + this->booleanValues.push_back(false); + } + + void SimpleValuation::addIntegerIdentifier(std::string const& name, int_fast64_t initialValue) { + this->integerIdentifierToIndexMap->emplace(name, this->integerValues.size()); + this->integerValues.push_back(initialValue); + } + + void SimpleValuation::addDoubleIdentifier(std::string const& name, double initialValue) { + this->doubleIdentifierToIndexMap->emplace(name, this->doubleValues.size()); + this->doubleValues.push_back(initialValue); + } + + void SimpleValuation::setBooleanValue(std::string const& name, bool value) { + this->booleanValues[this->booleanIdentifierToIndexMap->at(name)] = value; + } + + void SimpleValuation::setIntegerValue(std::string const& name, int_fast64_t value) { + this->integerValues[this->integerIdentifierToIndexMap->at(name)] = value; + } + + void SimpleValuation::setDoubleValue(std::string const& name, double value) { + this->doubleValues[this->doubleIdentifierToIndexMap->at(name)] = value; + } + + bool SimpleValuation::getBooleanValue(std::string const& name) const { + auto const& nameIndexPair = this->booleanIdentifierToIndexMap->find(name); + return this->booleanValues[nameIndexPair->second]; + } + + int_fast64_t SimpleValuation::getIntegerValue(std::string const& name) const { + auto const& nameIndexPair = this->integerIdentifierToIndexMap->find(name); + return this->integerValues[nameIndexPair->second]; + } + + double SimpleValuation::getDoubleValue(std::string const& name) const { + auto const& nameIndexPair = this->doubleIdentifierToIndexMap->find(name); + return this->doubleValues[nameIndexPair->second]; + } + + std::ostream& operator<<(std::ostream& stream, SimpleValuation const& valuation) { + stream << "valuation { bool ["; + if (!valuation.booleanValues.empty()) { + for (uint_fast64_t i = 0; i < valuation.booleanValues.size() - 1; ++i) { + stream << valuation.booleanValues[i] << ", "; + } + stream << valuation.booleanValues.back(); + } + stream << "] int ["; + if (!valuation.integerValues.empty()) { + for (uint_fast64_t i = 0; i < valuation.integerValues.size() - 1; ++i) { + stream << valuation.integerValues[i] << ", "; + } + stream << valuation.integerValues.back(); + } + stream << "] double ["; + if (!valuation.doubleValues.empty()) { + for (uint_fast64_t i = 0; i < valuation.doubleValues.size() - 1; ++i) { + stream << valuation.doubleValues[i] << ", "; + } + stream << valuation.doubleValues.back(); + } + stream << "] }"; + + return stream; + } + + std::size_t SimpleValuationPointerHash::operator()(SimpleValuation* valuation) const { + size_t seed = 0; + for (auto const& value : valuation->booleanValues) { + boost::hash_combine<bool>(seed, value); + } + for (auto const& value : valuation->integerValues) { + boost::hash_combine<int_fast64_t>(seed, value); + } + for (auto const& value : valuation->doubleValues) { + boost::hash_combine<double>(seed, value); + } + return seed; + } + + bool SimpleValuationPointerCompare::operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const { + return *valuation1 == *valuation2; + } + + bool SimpleValuationPointerLess::operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const { + // Compare boolean variables. + bool less = valuation1->booleanValues < valuation2->booleanValues; + if (less) { + return true; + } + less = valuation1->integerValues < valuation2->integerValues; + if (less) { + return true; + } + less = valuation1->doubleValues < valuation2->doubleValues; + if (less) { + return true; + } else { + return false; + } + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/SimpleValuation.h b/src/storage/expressions/SimpleValuation.h new file mode 100644 index 000000000..35b74291b --- /dev/null +++ b/src/storage/expressions/SimpleValuation.h @@ -0,0 +1,141 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_SIMPLEVALUATION_H_ +#define STORM_STORAGE_EXPRESSIONS_SIMPLEVALUATION_H_ + +#include <memory> +#include <vector> +#include <unordered_map> +#include <iostream> + +#include "src/storage/expressions/Valuation.h" + +namespace storm { + namespace expressions { + class SimpleValuation : public Valuation { + public: + friend class SimpleValuationPointerHash; + friend class SimpleValuationPointerLess; + + /*! + * Creates a simple valuation without any identifiers. + */ + SimpleValuation(); + + // Instantiate some constructors and assignments with their default implementations. + SimpleValuation(SimpleValuation const&) = default; + SimpleValuation& operator=(SimpleValuation const&) = default; + SimpleValuation(SimpleValuation&&) = default; + SimpleValuation& operator=(SimpleValuation&&) = default; + virtual ~SimpleValuation() = default; + + /*! + * Compares two simple valuations wrt. equality. + */ + bool operator==(SimpleValuation const& other) const; + + /*! + * Adds a boolean identifier with the given name. + * + * @param name The name of the boolean identifier to add. + * @param initialValue The initial value of the identifier. + */ + void addBooleanIdentifier(std::string const& name, bool initialValue = false); + + /*! + * Adds a integer identifier with the given name. + * + * @param name The name of the integer identifier to add. + * @param initialValue The initial value of the identifier. + */ + void addIntegerIdentifier(std::string const& name, int_fast64_t initialValue = 0); + + /*! + * Adds a double identifier with the given name. + * + * @param name The name of the double identifier to add. + * @param initialValue The initial value of the identifier. + */ + void addDoubleIdentifier(std::string const& name, double initialValue = 0); + + /*! + * Sets the value of the boolean identifier with the given name to the given value. + * + * @param name The name of the boolean identifier whose value to set. + * @param value The new value of the boolean identifier. + */ + void setBooleanValue(std::string const& name, bool value); + + /*! + * Sets the value of the integer identifier with the given name to the given value. + * + * @param name The name of the integer identifier whose value to set. + * @param value The new value of the integer identifier. + */ + void setIntegerValue(std::string const& name, int_fast64_t value); + + /*! + * Sets the value of the double identifier with the given name to the given value. + * + * @param name The name of the double identifier whose value to set. + * @param value The new value of the double identifier. + */ + void setDoubleValue(std::string const& name, double value); + + // Override base class methods. + virtual bool getBooleanValue(std::string const& name) const override; + virtual int_fast64_t getIntegerValue(std::string const& name) const override; + virtual double getDoubleValue(std::string const& name) const override; + + friend std::ostream& operator<<(std::ostream& stream, SimpleValuation const& valuation); + + private: + // A mapping of boolean identifiers to their local indices in the value container. + std::shared_ptr<std::unordered_map<std::string, uint_fast64_t>> booleanIdentifierToIndexMap; + + // A mapping of integer identifiers to their local indices in the value container. + std::shared_ptr<std::unordered_map<std::string, uint_fast64_t>> integerIdentifierToIndexMap; + + // A mapping of double identifiers to their local indices in the value container. + std::shared_ptr<std::unordered_map<std::string, uint_fast64_t>> doubleIdentifierToIndexMap; + + // The value container for all boolean identifiers. + std::vector<bool> booleanValues; + + // The value container for all integer identifiers. + std::vector<int_fast64_t> integerValues; + + // The value container for all double identifiers. + std::vector<double> doubleValues; + }; + + /*! + * A helper class that can pe used as the hash functor for data structures that need to hash a simple valuations + * given via pointers. + */ + class SimpleValuationPointerHash { + public: + std::size_t operator()(SimpleValuation* valuation) const; + }; + + /*! + * A helper class that can be used as the comparison functor wrt. equality for data structures that need to + * store pointers to a simple valuations and need to compare the elements wrt. their content (rather than + * pointer equality). + */ + class SimpleValuationPointerCompare { + public: + bool operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const; + }; + + /*! + * A helper class that can be used as the comparison functor wrt. "<" for data structures that need to + * store pointers to a simple valuations and need to compare the elements wrt. their content (rather than + * pointer equality). + */ + class SimpleValuationPointerLess { + public: + bool operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_SIMPLEVALUATION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/SubstitutionVisitor.cpp b/src/storage/expressions/SubstitutionVisitor.cpp new file mode 100644 index 000000000..c3f2ea0a8 --- /dev/null +++ b/src/storage/expressions/SubstitutionVisitor.cpp @@ -0,0 +1,200 @@ +#include <map> +#include <unordered_map> + +#include "src/storage/expressions/SubstitutionVisitor.h" + +#include "src/storage/expressions/IfThenElseExpression.h" +#include "src/storage/expressions/BinaryBooleanFunctionExpression.h" +#include "src/storage/expressions/BinaryNumericalFunctionExpression.h" +#include "src/storage/expressions/BinaryRelationExpression.h" +#include "src/storage/expressions/BooleanConstantExpression.h" +#include "src/storage/expressions/IntegerConstantExpression.h" +#include "src/storage/expressions/DoubleConstantExpression.h" +#include "src/storage/expressions/BooleanLiteralExpression.h" +#include "src/storage/expressions/IntegerLiteralExpression.h" +#include "src/storage/expressions/DoubleLiteralExpression.h" +#include "src/storage/expressions/VariableExpression.h" +#include "src/storage/expressions/UnaryBooleanFunctionExpression.h" +#include "src/storage/expressions/UnaryNumericalFunctionExpression.h" + +namespace storm { + namespace expressions { + template<template<typename... Arguments> class MapType> + SubstitutionVisitor<MapType>::SubstitutionVisitor(MapType<std::string, Expression> const& identifierToExpressionMap) : identifierToExpressionMap(identifierToExpressionMap) { + // Intentionally left empty. + } + + template<template<typename... Arguments> class MapType> + Expression SubstitutionVisitor<MapType>::substitute(BaseExpression const* expression) { + expression->accept(this); + return Expression(this->expressionStack.top()); + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(IfThenElseExpression const* expression) { + expression->getCondition()->accept(this); + std::shared_ptr<BaseExpression const> conditionExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getThenExpression()->accept(this); + std::shared_ptr<BaseExpression const> thenExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getElseExpression()->accept(this); + std::shared_ptr<BaseExpression const> elseExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (conditionExpression.get() == expression->getCondition().get() && thenExpression.get() == expression->getThenExpression().get() && elseExpression.get() == expression->getElseExpression().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new IfThenElseExpression(expression->getReturnType(), conditionExpression, thenExpression, elseExpression))); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(BinaryBooleanFunctionExpression const* expression) { + expression->getFirstOperand()->accept(this); + std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getSecondOperand()->accept(this); + std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(BinaryNumericalFunctionExpression const* expression) { + expression->getFirstOperand()->accept(this); + std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getSecondOperand()->accept(this); + std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(BinaryRelationExpression const* expression) { + expression->getFirstOperand()->accept(this); + std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top(); + expressionStack.pop(); + + expression->getSecondOperand()->accept(this); + std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top(); + expressionStack.pop(); + + // If the arguments did not change, we simply push the expression itself. + if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) { + this->expressionStack.push(expression->getSharedPointer()); + } else { + this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getRelationType()))); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(BooleanConstantExpression const* expression) { + // If the boolean constant is in the key set of the substitution, we need to replace it. + auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getConstantName()); + if (nameExpressionPair != this->identifierToExpressionMap.end()) { + this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer()); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(DoubleConstantExpression const* expression) { + // If the double constant is in the key set of the substitution, we need to replace it. + auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getConstantName()); + if (nameExpressionPair != this->identifierToExpressionMap.end()) { + this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer()); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(IntegerConstantExpression const* expression) { + // If the integer constant is in the key set of the substitution, we need to replace it. + auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getConstantName()); + if (nameExpressionPair != this->identifierToExpressionMap.end()) { + this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer()); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(VariableExpression const* expression) { + // If the variable is in the key set of the substitution, we need to replace it. + auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getVariableName()); + if (nameExpressionPair != this->identifierToExpressionMap.end()) { + this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer()); + } else { + this->expressionStack.push(expression->getSharedPointer()); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(UnaryBooleanFunctionExpression const* expression) { + expression->getOperand()->accept(this); + std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top(); + expressionStack.pop(); + + // If the argument did not change, we simply push the expression itself. + if (operandExpression.get() == expression->getOperand().get()) { + expressionStack.push(expression->getSharedPointer()); + } else { + expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(UnaryNumericalFunctionExpression const* expression) { + expression->getOperand()->accept(this); + std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top(); + expressionStack.pop(); + + // If the argument did not change, we simply push the expression itself. + if (operandExpression.get() == expression->getOperand().get()) { + expressionStack.push(expression->getSharedPointer()); + } else { + expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType()))); + } + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(BooleanLiteralExpression const* expression) { + this->expressionStack.push(expression->getSharedPointer()); + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(IntegerLiteralExpression const* expression) { + this->expressionStack.push(expression->getSharedPointer()); + } + + template<template<typename... Arguments> class MapType> + void SubstitutionVisitor<MapType>::visit(DoubleLiteralExpression const* expression) { + this->expressionStack.push(expression->getSharedPointer()); + } + + // Explicitly instantiate the class with map and unordered_map. + template class SubstitutionVisitor<std::map>; + template class SubstitutionVisitor<std::unordered_map>; + } +} diff --git a/src/storage/expressions/SubstitutionVisitor.h b/src/storage/expressions/SubstitutionVisitor.h new file mode 100644 index 000000000..ad29ad6ab --- /dev/null +++ b/src/storage/expressions/SubstitutionVisitor.h @@ -0,0 +1,55 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_SUBSTITUTIONVISITOR_H_ +#define STORM_STORAGE_EXPRESSIONS_SUBSTITUTIONVISITOR_H_ + +#include <stack> + +#include "src/storage/expressions/Expression.h" +#include "src/storage/expressions/ExpressionVisitor.h" + +namespace storm { + namespace expressions { + template<template<typename... Arguments> class MapType> + class SubstitutionVisitor : public ExpressionVisitor { + public: + /*! + * Creates a new substitution visitor that uses the given map to replace identifiers. + * + * @param identifierToExpressionMap A mapping from identifiers to expressions. + */ + SubstitutionVisitor(MapType<std::string, Expression> const& identifierToExpressionMap); + + /*! + * Substitutes the identifiers in the given expression according to the previously given map and returns the + * resulting expression. + * + * @param expression The expression in which to substitute the identifiers. + * @return The expression in which all identifiers in the key set of the previously given mapping are + * substituted with the mapped-to expressions. + */ + Expression substitute(BaseExpression const* expression); + + virtual void visit(IfThenElseExpression const* expression) override; + virtual void visit(BinaryBooleanFunctionExpression const* expression) override; + virtual void visit(BinaryNumericalFunctionExpression const* expression) override; + virtual void visit(BinaryRelationExpression const* expression) override; + virtual void visit(BooleanConstantExpression const* expression) override; + virtual void visit(DoubleConstantExpression const* expression) override; + virtual void visit(IntegerConstantExpression const* expression) override; + virtual void visit(VariableExpression const* expression) override; + virtual void visit(UnaryBooleanFunctionExpression const* expression) override; + virtual void visit(UnaryNumericalFunctionExpression const* expression) override; + virtual void visit(BooleanLiteralExpression const* expression) override; + virtual void visit(IntegerLiteralExpression const* expression) override; + virtual void visit(DoubleLiteralExpression const* expression) override; + + private: + // A stack of expression used to pass the results to the higher levels. + std::stack<std::shared_ptr<BaseExpression const>> expressionStack; + + // A mapping of identifier names to expressions with which they shall be replaced. + MapType<std::string, Expression> const& identifierToExpressionMap; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_SUBSTITUTIONVISITOR_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/UnaryBooleanFunctionExpression.cpp b/src/storage/expressions/UnaryBooleanFunctionExpression.cpp new file mode 100644 index 000000000..7e405bb29 --- /dev/null +++ b/src/storage/expressions/UnaryBooleanFunctionExpression.cpp @@ -0,0 +1,50 @@ +#include "src/storage/expressions/UnaryBooleanFunctionExpression.h" +#include "src/storage/expressions/BooleanLiteralExpression.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidTypeException.h" + +namespace storm { + namespace expressions { + UnaryBooleanFunctionExpression::UnaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType) : UnaryExpression(returnType, operand), operatorType(operatorType) { + // Intentionally left empty. + } + + UnaryBooleanFunctionExpression::OperatorType UnaryBooleanFunctionExpression::getOperatorType() const { + return this->operatorType; + } + + bool UnaryBooleanFunctionExpression::evaluateAsBool(Valuation const* valuation) const { + LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean."); + + bool operandEvaluated = this->getOperand()->evaluateAsBool(valuation); + switch (this->getOperatorType()) { + case OperatorType::Not: return !operandEvaluated; break; + } + } + + std::shared_ptr<BaseExpression const> UnaryBooleanFunctionExpression::simplify() const { + std::shared_ptr<BaseExpression const> operandSimplified = this->getOperand()->simplify(); + switch (this->getOperatorType()) { + case OperatorType::Not: if (operandSimplified->isTrue()) { + return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(false)); + } else { + return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true)); + } + } + + if (operandSimplified.get() == this->getOperand().get()) { + return this->shared_from_this(); + } else { + return std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(this->getReturnType(), operandSimplified, this->getOperatorType())); + } + } + + void UnaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + void UnaryBooleanFunctionExpression::printToStream(std::ostream& stream) const { + stream << "!(" << *this->getOperand() << ")"; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/UnaryBooleanFunctionExpression.h b/src/storage/expressions/UnaryBooleanFunctionExpression.h new file mode 100644 index 000000000..1f2800d8e --- /dev/null +++ b/src/storage/expressions/UnaryBooleanFunctionExpression.h @@ -0,0 +1,57 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ + +#include "src/storage/expressions/UnaryExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class UnaryBooleanFunctionExpression : public UnaryExpression { + public: + /*! + * An enum type specifying the different functions applicable. + */ + enum class OperatorType { Not }; + + /*! + * Creates a unary boolean function expression with the given return type, operand and operator. + * + * @param returnType The return type of the expression. + * @param operand The operand of the expression. + * @param operatorType The operator of the expression. + */ + UnaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType); + + // Instantiate constructors and assignments with their default implementations. + UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression const& other) = default; + UnaryBooleanFunctionExpression& operator=(UnaryBooleanFunctionExpression const& other) = default; +#ifndef WINDOWS + UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression&&) = default; + UnaryBooleanFunctionExpression& operator=(UnaryBooleanFunctionExpression&&) = default; +#endif + virtual ~UnaryBooleanFunctionExpression() = default; + + // Override base class methods. + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the operator associated with this expression. + * + * @return The operator associated with this expression. + */ + OperatorType getOperatorType() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The operator of this expression. + OperatorType operatorType; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ */ diff --git a/src/storage/expressions/UnaryExpression.cpp b/src/storage/expressions/UnaryExpression.cpp new file mode 100644 index 000000000..1e2d9135e --- /dev/null +++ b/src/storage/expressions/UnaryExpression.cpp @@ -0,0 +1,25 @@ +#include "src/storage/expressions/UnaryExpression.h" + +namespace storm { + namespace expressions { + UnaryExpression::UnaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand) : BaseExpression(returnType), operand(operand) { + // Intentionally left empty. + } + + bool UnaryExpression::isConstant() const { + return this->getOperand()->isConstant(); + } + + std::set<std::string> UnaryExpression::getVariables() const { + return this->getOperand()->getVariables(); + } + + std::set<std::string> UnaryExpression::getConstants() const { + return this->getOperand()->getVariables(); + } + + std::shared_ptr<BaseExpression const> const& UnaryExpression::getOperand() const { + return this->operand; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/UnaryExpression.h b/src/storage/expressions/UnaryExpression.h new file mode 100644 index 000000000..f81bc08ad --- /dev/null +++ b/src/storage/expressions/UnaryExpression.h @@ -0,0 +1,47 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_UNARYEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_UNARYEXPRESSION_H_ + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class UnaryExpression : public BaseExpression { + public: + /*! + * Creates a unary expression with the given return type and operand. + * + * @param returnType The return type of the expression. + * @param operand The operand of the unary expression. + */ + UnaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand); + + // Instantiate constructors and assignments with their default implementations. + UnaryExpression(UnaryExpression const& other); + UnaryExpression& operator=(UnaryExpression const& other); +#ifndef WINDOWS + UnaryExpression(UnaryExpression&&) = default; + UnaryExpression& operator=(UnaryExpression&&) = default; +#endif + virtual ~UnaryExpression() = default; + + // Override base class methods. + virtual bool isConstant() const override; + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + + /*! + * Retrieves the operand of the unary expression. + * + * @return The operand of the unary expression. + */ + std::shared_ptr<BaseExpression const> const& getOperand() const; + + private: + // The operand of the unary expression. + std::shared_ptr<BaseExpression const> operand; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_UNARYEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/UnaryNumericalFunctionExpression.cpp b/src/storage/expressions/UnaryNumericalFunctionExpression.cpp new file mode 100644 index 000000000..02a4bee30 --- /dev/null +++ b/src/storage/expressions/UnaryNumericalFunctionExpression.cpp @@ -0,0 +1,62 @@ +#include <cmath> + +#include "src/storage/expressions/UnaryNumericalFunctionExpression.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidTypeException.h" + +namespace storm { + namespace expressions { + UnaryNumericalFunctionExpression::UnaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType) : UnaryExpression(returnType, operand), operatorType(operatorType) { + // Intentionally left empty. + } + + UnaryNumericalFunctionExpression::OperatorType UnaryNumericalFunctionExpression::getOperatorType() const { + return this->operatorType; + } + + int_fast64_t UnaryNumericalFunctionExpression::evaluateAsInt(Valuation const* valuation) const { + LOG_THROW(this->hasIntegralReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as integer."); + + int_fast64_t operandEvaluated = this->getOperand()->evaluateAsInt(valuation); + switch (this->getOperatorType()) { + case OperatorType::Minus: return -operandEvaluated; break; + case OperatorType::Floor: return std::floor(operandEvaluated); break; + case OperatorType::Ceil: return std::ceil(operandEvaluated); break; + } + } + + double UnaryNumericalFunctionExpression::evaluateAsDouble(Valuation const* valuation) const { + LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as double."); + + double operandEvaluated = this->getOperand()->evaluateAsDouble(valuation); + switch (this->getOperatorType()) { + case OperatorType::Minus: return -operandEvaluated; break; + case OperatorType::Floor: return std::floor(operandEvaluated); break; + case OperatorType::Ceil: return std::ceil(operandEvaluated); break; + } + } + + std::shared_ptr<BaseExpression const> UnaryNumericalFunctionExpression::simplify() const { + std::shared_ptr<BaseExpression const> operandSimplified = this->getOperand()->simplify(); + + if (operandSimplified.get() == this->getOperand().get()) { + return this->shared_from_this(); + } else { + return std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getReturnType(), operandSimplified, this->getOperatorType())); + } + } + + void UnaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + void UnaryNumericalFunctionExpression::printToStream(std::ostream& stream) const { + switch (this->getOperatorType()) { + case OperatorType::Minus: stream << "-("; break; + case OperatorType::Floor: stream << "floor("; break; + case OperatorType::Ceil: stream << "ceil("; break; + } + stream << *this->getOperand() << ")"; + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/UnaryNumericalFunctionExpression.h b/src/storage/expressions/UnaryNumericalFunctionExpression.h new file mode 100644 index 000000000..daa0df40f --- /dev/null +++ b/src/storage/expressions/UnaryNumericalFunctionExpression.h @@ -0,0 +1,58 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_UNARYNUMERICALFUNCTIONEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_UNARYNUMERICALFUNCTIONEXPRESSION_H_ + +#include "src/storage/expressions/UnaryExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class UnaryNumericalFunctionExpression : public UnaryExpression { + public: + /*! + * An enum type specifying the different functions applicable. + */ + enum class OperatorType {Minus, Floor, Ceil}; + + /*! + * Creates a unary numerical function expression with the given return type, operand and operator. + * + * @param returnType The return type of the expression. + * @param operand The operand of the expression. + * @param operatorType The operator of the expression. + */ + UnaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType); + + // Instantiate constructors and assignments with their default implementations. + UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression const& other) = default; + UnaryNumericalFunctionExpression& operator=(UnaryNumericalFunctionExpression const& other) = default; +#ifndef WINDOWS + UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression&&) = default; + UnaryNumericalFunctionExpression& operator=(UnaryNumericalFunctionExpression&&) = default; +#endif + virtual ~UnaryNumericalFunctionExpression() = default; + + // Override base class methods. + virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override; + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the operator associated with this expression. + * + * @return The operator associated with this expression. + */ + OperatorType getOperatorType() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The operator of this expression. + OperatorType operatorType; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_UNARYNUMERICALFUNCTIONEXPRESSION_H_ */ diff --git a/src/storage/expressions/Valuation.h b/src/storage/expressions/Valuation.h new file mode 100644 index 000000000..7aa32a859 --- /dev/null +++ b/src/storage/expressions/Valuation.h @@ -0,0 +1,41 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_VALUATION_H_ +#define STORM_STORAGE_EXPRESSIONS_VALUATION_H_ + +#include <string> + +namespace storm { + namespace expressions { + /*! + * The base class of all valuations where a valuation assigns a concrete value to all identifiers. This is, for + * example, used for evaluating expressions. + */ + class Valuation { + public: + /*! + * Retrieves the boolean value of the identifier with the given name. + * + * @param name The name of the boolean identifier whose value to retrieve. + * @return The value of the boolean identifier. + */ + virtual bool getBooleanValue(std::string const& name) const = 0; + + /*! + * Retrieves the integer value of the identifier with the given name. + * + * @param name The name of the integer identifier whose value to retrieve. + * @return The value of the integer identifier. + */ + virtual int_fast64_t getIntegerValue(std::string const& name) const = 0; + + /*! + * Retrieves the double value of the identifier with the given name. + * + * @param name The name of the double identifier whose value to retrieve. + * @return The value of the double identifier. + */ + virtual double getDoubleValue(std::string const& name) const = 0; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_VALUATION_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/VariableExpression.cpp b/src/storage/expressions/VariableExpression.cpp new file mode 100644 index 000000000..d7765f14a --- /dev/null +++ b/src/storage/expressions/VariableExpression.cpp @@ -0,0 +1,64 @@ +#include "src/storage/expressions/VariableExpression.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidTypeException.h" + +namespace storm { + namespace expressions { + VariableExpression::VariableExpression(ExpressionReturnType returnType, std::string const& variableName) : BaseExpression(returnType), variableName(variableName) { + // Intentionally left empty. + } + + std::string const& VariableExpression::getVariableName() const { + return this->variableName; + } + + bool VariableExpression::evaluateAsBool(Valuation const* valuation) const { + LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation."); + LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Cannot evaluate expression as boolean: return type is not a boolean."); + + return valuation->getBooleanValue(this->getVariableName()); + } + + int_fast64_t VariableExpression::evaluateAsInt(Valuation const* valuation) const { + LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation."); + LOG_THROW(this->hasIntegralReturnType(), storm::exceptions::InvalidTypeException, "Cannot evaluate expression as integer: return type is not an integer."); + + return valuation->getIntegerValue(this->getVariableName()); + } + + double VariableExpression::evaluateAsDouble(Valuation const* valuation) const { + LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation."); + LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Cannot evaluate expression as double: return type is not a double."); + + switch (this->getReturnType()) { + case ExpressionReturnType::Int: return static_cast<double>(valuation->getIntegerValue(this->getVariableName())); break; + case ExpressionReturnType::Double: valuation->getDoubleValue(this->getVariableName()); break; + default: break; + } + LOG_ASSERT(false, "Type of variable is required to be numeric."); + + // Silence warning. This point can never be reached. + return 0; + } + + std::set<std::string> VariableExpression::getVariables() const { + return {this->getVariableName()}; + } + + std::set<std::string> VariableExpression::getConstants() const { + return std::set<std::string>(); + } + + std::shared_ptr<BaseExpression const> VariableExpression::simplify() const { + return this->shared_from_this(); + } + + void VariableExpression::accept(ExpressionVisitor* visitor) const { + visitor->visit(this); + } + + void VariableExpression::printToStream(std::ostream& stream) const { + stream << this->getVariableName(); + } + } +} \ No newline at end of file diff --git a/src/storage/expressions/VariableExpression.h b/src/storage/expressions/VariableExpression.h new file mode 100644 index 000000000..2d83b7160 --- /dev/null +++ b/src/storage/expressions/VariableExpression.h @@ -0,0 +1,55 @@ +#ifndef STORM_STORAGE_EXPRESSIONS_VARIABLEEXPRESSION_H_ +#define STORM_STORAGE_EXPRESSIONS_VARIABLEEXPRESSION_H_ + +#include "src/storage/expressions/BaseExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace expressions { + class VariableExpression : public BaseExpression { + public: + /*! + * Creates a variable expression with the given return type and variable name. + * + * @param returnType The return type of the variable expression. + * @param variableName The name of the variable associated with this expression. + */ + VariableExpression(ExpressionReturnType returnType, std::string const& variableName); + + // Instantiate constructors and assignments with their default implementations. + VariableExpression(VariableExpression const&) = default; + VariableExpression& operator=(VariableExpression const&) = default; +#ifndef WINDOWS + VariableExpression(VariableExpression&&) = default; + VariableExpression& operator=(VariableExpression&&) = default; +#endif + virtual ~VariableExpression() = default; + + // Override base class methods. + virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override; + virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override; + virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override; + virtual std::set<std::string> getVariables() const override; + virtual std::set<std::string> getConstants() const override; + virtual std::shared_ptr<BaseExpression const> simplify() const override; + virtual void accept(ExpressionVisitor* visitor) const override; + + /*! + * Retrieves the name of the variable associated with this expression. + * + * @return The name of the variable. + */ + std::string const& getVariableName() const; + + protected: + // Override base class method. + virtual void printToStream(std::ostream& stream) const override; + + private: + // The variable name associated with this expression. + std::string variableName; + }; + } +} + +#endif /* STORM_STORAGE_EXPRESSIONS_VARIABLEEXPRESSION_H_ */ \ No newline at end of file diff --git a/src/storage/prism/Assignment.cpp b/src/storage/prism/Assignment.cpp new file mode 100644 index 000000000..f15797e6d --- /dev/null +++ b/src/storage/prism/Assignment.cpp @@ -0,0 +1,27 @@ +#include "Assignment.h" + +namespace storm { + namespace prism { + Assignment::Assignment(std::string const& variableName, storm::expressions::Expression const& expression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), variableName(variableName), expression(expression) { + // Intentionally left empty. + } + + std::string const& Assignment::getVariableName() const { + return variableName; + } + + storm::expressions::Expression const& Assignment::getExpression() const { + return this->expression; + } + + Assignment Assignment::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return Assignment(this->getVariableName(), this->getExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, Assignment const& assignment) { + stream << "(" << assignment.getVariableName() << "' = " << assignment.getExpression() << ")"; + return stream; + } + + } // namespace prism +} // namespace storm diff --git a/src/storage/prism/Assignment.h b/src/storage/prism/Assignment.h new file mode 100644 index 000000000..c6604a03e --- /dev/null +++ b/src/storage/prism/Assignment.h @@ -0,0 +1,67 @@ +#ifndef STORM_STORAGE_PRISM_ASSIGNMENT_H_ +#define STORM_STORAGE_PRISM_ASSIGNMENT_H_ + +#include <map> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/expressions/Expression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Assignment : public LocatedInformation { + public: + /*! + * Constructs an assignment using the given variable name and expression. + * + * @param variableName The variable that this assignment targets. + * @param expression The expression to assign to the variable. + * @param filename The filename in which the assignment is defined. + * @param lineNumber The line number in which the assignment is defined. + */ + Assignment(std::string const& variableName, storm::expressions::Expression const& expression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + Assignment() = default; + Assignment(Assignment const& other) = default; + Assignment& operator=(Assignment const& other)= default; +#ifndef WINDOWS + Assignment(Assignment&& other) = default; + Assignment& operator=(Assignment&& other) = default; +#endif + + /*! + * Retrieves the name of the variable that this assignment targets. + * + * @return The name of the variable that this assignment targets. + */ + std::string const& getVariableName() const; + + /*! + * Retrieves the expression that is assigned to the variable. + * + * @return The expression that is assigned to the variable. + */ + storm::expressions::Expression const& getExpression() const; + + /*! + * Substitutes all identifiers in the assignment according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting assignment. + */ + Assignment substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, Assignment const& assignment); + + private: + // The name of the variable that this assignment targets. + std::string variableName; + + // The expression that is assigned to the variable. + storm::expressions::Expression expression; + }; + } // namespace ir +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_ASSIGNMENT_H_ */ diff --git a/src/storage/prism/BooleanVariable.cpp b/src/storage/prism/BooleanVariable.cpp new file mode 100644 index 000000000..478b9322d --- /dev/null +++ b/src/storage/prism/BooleanVariable.cpp @@ -0,0 +1,23 @@ +#include "src/storage/prism/BooleanVariable.h" + +namespace storm { + namespace prism { + BooleanVariable::BooleanVariable(std::string const& variableName, std::string const& filename, uint_fast64_t lineNumber) : Variable(variableName, storm::expressions::Expression::createFalse(), true, filename, lineNumber) { + // Nothing to do here. + } + + BooleanVariable::BooleanVariable(std::string const& variableName, storm::expressions::Expression const& initialValueExpression, std::string const& filename, uint_fast64_t lineNumber) : Variable(variableName, initialValueExpression, false, filename, lineNumber) { + // Nothing to do here. + } + + BooleanVariable BooleanVariable::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return BooleanVariable(this->getName(), this->getInitialValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, BooleanVariable const& variable) { + stream << variable.getName() << ": bool " << variable.getInitialValueExpression() << ";"; + return stream; + } + + } // namespace prism +} // namespace storm diff --git a/src/storage/prism/BooleanVariable.h b/src/storage/prism/BooleanVariable.h new file mode 100644 index 000000000..f32035010 --- /dev/null +++ b/src/storage/prism/BooleanVariable.h @@ -0,0 +1,55 @@ +#ifndef STORM_STORAGE_PRISM_BOOLEANVARIABLE_H_ +#define STORM_STORAGE_PRISM_BOOLEANVARIABLE_H_ + +#include <map> + +#include "src/storage/prism/Variable.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class BooleanVariable : public Variable { + public: + // Create default implementations of constructors/assignment. + BooleanVariable() = default; + BooleanVariable(BooleanVariable const& other) = default; + BooleanVariable& operator=(BooleanVariable const& other)= default; +#ifndef WINDOWS + BooleanVariable(BooleanVariable&& other) = default; + BooleanVariable& operator=(BooleanVariable&& other) = default; +#endif + + /*! + * Creates a boolean variable with the given name and the default initial value expression. + * + * @param variableName The name of the variable. + * @param filename The filename in which the variable is defined. + * @param lineNumber The line number in which the variable is defined. + */ + BooleanVariable(std::string const& variableName, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + /*! + * Creates a boolean variable with the given name and the given constant initial value expression. + * + * @param variableName The name of the variable. + * @param initialValueExpression The constant expression that defines the initial value of the variable. + * @param filename The filename in which the variable is defined. + * @param lineNumber The line number in which the variable is defined. + */ + BooleanVariable(std::string const& variableName, storm::expressions::Expression const& initialValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + /*! + * Substitutes all identifiers in the boolean variable according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting boolean variable. + */ + BooleanVariable substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, BooleanVariable const& variable); + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_BOOLEANVARIABLE_H_ */ diff --git a/src/storage/prism/Command.cpp b/src/storage/prism/Command.cpp new file mode 100644 index 000000000..f075ff6c6 --- /dev/null +++ b/src/storage/prism/Command.cpp @@ -0,0 +1,55 @@ +#include "Command.h" + +namespace storm { + namespace prism { + Command::Command(uint_fast64_t globalIndex, std::string const& actionName, storm::expressions::Expression const& guardExpression, std::vector<storm::prism::Update> const& updates, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), actionName(actionName), guardExpression(guardExpression), updates(updates), globalIndex(globalIndex) { + // Nothing to do here. + } + + std::string const& Command::getActionName() const { + return this->actionName; + } + + storm::expressions::Expression const& Command::getGuardExpression() const { + return guardExpression; + } + + std::size_t Command::getNumberOfUpdates() const { + return this->updates.size(); + } + + storm::prism::Update const& Command::getUpdate(uint_fast64_t index) const { + return this->updates[index]; + } + + std::vector<storm::prism::Update> const& Command::getUpdates() const { + return this->updates; + } + + uint_fast64_t Command::getGlobalIndex() const { + return this->globalIndex; + } + + Command Command::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + std::vector<Update> newUpdates; + newUpdates.reserve(this->getNumberOfUpdates()); + for (auto const& update : this->getUpdates()) { + newUpdates.emplace_back(update.substitute(substitution)); + } + + return Command(this->getGlobalIndex(), this->getActionName(), this->getGuardExpression().substitute<std::map>(substitution), newUpdates, this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, Command const& command) { + stream << "[" << command.getActionName() << "] " << command.getGuardExpression() << " -> "; + for (uint_fast64_t i = 0; i < command.getUpdates().size(); ++i) { + stream << command.getUpdate(i); + if (i < command.getUpdates().size() - 1) { + stream << " + "; + } + } + stream << ";"; + return stream; + } + } // namespace ir +} // namespace storm diff --git a/src/storage/prism/Command.h b/src/storage/prism/Command.h new file mode 100644 index 000000000..6e32eba5e --- /dev/null +++ b/src/storage/prism/Command.h @@ -0,0 +1,106 @@ +#ifndef STORM_STORAGE_PRISM_COMMAND_H_ +#define STORM_STORAGE_PRISM_COMMAND_H_ + +#include <vector> +#include <string> +#include <map> + +#include "src/storage/expressions/Expression.h" +#include "src/storage/prism/Update.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Command : public LocatedInformation { + public: + /*! + * Creates a command with the given action name, guard and updates. + * + * @param globalIndex The global index of the command. + * @param actionName The action name of the command. + * @param guardExpression the expression that defines the guard of the command. + * @param updates A list of updates that is associated with this command. + * @param filename The filename in which the command is defined. + * @param lineNumber The line number in which the command is defined. + */ + Command(uint_fast64_t globalIndex, std::string const& actionName, storm::expressions::Expression const& guardExpression, std::vector<storm::prism::Update> const& updates, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + Command() = default; + Command(Command const& other) = default; + Command& operator=(Command const& other)= default; +#ifndef WINDOWS + Command(Command&& other) = default; + Command& operator=(Command&& other) = default; +#endif + + /*! + * Retrieves the action name of this command. + * + * @return The action name of this command. + */ + std::string const& getActionName() const; + + /*! + * Retrieves a reference to the guard of the command. + * + * @return A reference to the guard of the command. + */ + storm::expressions::Expression const& getGuardExpression() const; + + /*! + * Retrieves the number of updates associated with this command. + * + * @return The number of updates associated with this command. + */ + std::size_t getNumberOfUpdates() const; + + /*! + * Retrieves a reference to the update with the given index. + * + * @return A reference to the update with the given index. + */ + storm::prism::Update const& getUpdate(uint_fast64_t index) const; + + /*! + * Retrieves a vector of all updates associated with this command. + * + * @return A vector of updates associated with this command. + */ + std::vector<storm::prism::Update> const& getUpdates() const; + + /*! + * Retrieves the global index of the command, that is, a unique index over all modules. + * + * @return The global index of the command. + */ + uint_fast64_t getGlobalIndex() const; + + /*! + * Substitutes all identifiers in the command according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting command. + */ + Command substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, Command const& command); + + private: + // The name of the command. + std::string actionName; + + // The expression that defines the guard of the command. + storm::expressions::Expression guardExpression; + + // The list of updates of the command. + std::vector<storm::prism::Update> updates; + + // The global index of the command. + uint_fast64_t globalIndex; + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_COMMAND_H_ */ diff --git a/src/storage/prism/Constant.cpp b/src/storage/prism/Constant.cpp new file mode 100644 index 000000000..160e9ad22 --- /dev/null +++ b/src/storage/prism/Constant.cpp @@ -0,0 +1,49 @@ +#include "src/storage/prism/Constant.h" + +namespace storm { + namespace prism { + Constant::Constant(storm::expressions::ExpressionReturnType type, std::string const& name, storm::expressions::Expression const& expression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), type(type), name(name), defined(true), expression(expression) { + // Intentionally left empty. + } + + Constant::Constant(storm::expressions::ExpressionReturnType type, std::string const& name, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), type(type), name(name), defined(false), expression() { + // Intentionally left empty. + } + + std::string const& Constant::getName() const { + return this->name; + } + + storm::expressions::ExpressionReturnType Constant::getType() const { + return this->type; + } + + bool Constant::isDefined() const { + return this->defined; + } + + storm::expressions::Expression const& Constant::getExpression() const { + return this->expression; + } + + Constant Constant::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return Constant(this->getType(), this->getName(), this->getExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, Constant const& constant) { + stream << "const "; + switch (constant.getType()) { + case storm::expressions::ExpressionReturnType::Undefined: stream << "undefined "; break; + case storm::expressions::ExpressionReturnType::Bool: stream << "bool "; break; + case storm::expressions::ExpressionReturnType::Int: stream << "int "; break; + case storm::expressions::ExpressionReturnType::Double: stream << "double "; break; + } + stream << constant.getName(); + if (constant.isDefined()) { + stream << " = " << constant.getExpression(); + } + stream << ";"; + return stream; + } + } +} \ No newline at end of file diff --git a/src/storage/prism/Constant.h b/src/storage/prism/Constant.h new file mode 100644 index 000000000..2e1c27590 --- /dev/null +++ b/src/storage/prism/Constant.h @@ -0,0 +1,99 @@ +#ifndef STORM_STORAGE_PRISM_CONSTANT_H_ +#define STORM_STORAGE_PRISM_CONSTANT_H_ + +#include <map> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/expressions/Expression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Constant : public LocatedInformation { + public: + /*! + * Creates a constant with the given type, name and defining expression. + * + * @param type The type of the constant. + * @param name The name of the constant. + * @param expression The expression that defines the constant. + * @param filename The filename in which the transition reward is defined. + * @param lineNumber The line number in which the transition reward is defined. + */ + Constant(storm::expressions::ExpressionReturnType type, std::string const& name, storm::expressions::Expression const& expression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + /*! + * Creates an undefined constant with the given type and name. + * + * @param constantType The type of the constant. + * @param constantName The name of the constant. + * @param filename The filename in which the transition reward is defined. + * @param lineNumber The line number in which the transition reward is defined. + */ + Constant(storm::expressions::ExpressionReturnType constantType, std::string const& constantName, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + Constant() = default; + Constant(Constant const& other) = default; + Constant& operator=(Constant const& other)= default; +#ifndef WINDOWS + Constant(Constant&& other) = default; + Constant& operator=(Constant&& other) = default; +#endif + + /*! + * Retrieves the name of the constant. + * + * @return The name of the constant. + */ + std::string const& getName() const; + + /*! + * Retrieves the type of the constant. + * + * @return The type of the constant; + */ + storm::expressions::ExpressionReturnType getType() const; + + /*! + * Retrieves whether the constant is defined, i.e., whether there is an expression defining its value. + * + * @return True iff the constant is defined. + */ + bool isDefined() const; + + /*! + * Retrieves the expression that defines the constant. This may only be called if the object is a defined + * constant. + * + * @return The expression that defines the constant. + */ + storm::expressions::Expression const& getExpression() const; + + /*! + * Substitutes all identifiers in the constant according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting constant. + */ + Constant substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, Constant const& constant); + + private: + // The type of the constant. + storm::expressions::ExpressionReturnType type; + + // The name of the constant. + std::string name; + + // A flag that stores whether or not the constant is defined. + bool defined; + + // The expression that defines the constant (in case it is defined). + storm::expressions::Expression expression; + }; + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_CONSTANT_H_ */ diff --git a/src/storage/prism/Formula.cpp b/src/storage/prism/Formula.cpp new file mode 100644 index 000000000..3bf72a7de --- /dev/null +++ b/src/storage/prism/Formula.cpp @@ -0,0 +1,30 @@ +#include "src/storage/prism/Formula.h" + +namespace storm { + namespace prism { + Formula::Formula(std::string const& name, storm::expressions::Expression const& expression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(name), expression(expression) { + // Intentionally left empty. + } + + std::string const& Formula::getName() const { + return this->name; + } + + storm::expressions::Expression const& Formula::getExpression() const { + return this->expression; + } + + storm::expressions::ExpressionReturnType Formula::getType() const { + return this->getExpression().getReturnType(); + } + + Formula Formula::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return Formula(this->getName(), this->getExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, Formula const& formula) { + stream << "formula " << formula.getName() << " = " << formula.getExpression() << ";"; + return stream; + } + } +} \ No newline at end of file diff --git a/src/storage/prism/Formula.h b/src/storage/prism/Formula.h new file mode 100644 index 000000000..2df8e6d32 --- /dev/null +++ b/src/storage/prism/Formula.h @@ -0,0 +1,74 @@ +#ifndef STORM_STORAGE_PRISM_FORMULA_H_ +#define STORM_STORAGE_PRISM_FORMULA_H_ + +#include <map> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/expressions/Expression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Formula : public LocatedInformation { + public: + /*! + * Creates a formula with the given name and expression. + * + * @param name The name of the formula. + * @param expression The expression associated with this formula. + * @param filename The filename in which the transition reward is defined. + * @param lineNumber The line number in which the transition reward is defined. + */ + Formula(std::string const& name, storm::expressions::Expression const& expression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + Formula() = default; + Formula(Formula const& other) = default; + Formula& operator=(Formula const& other)= default; +#ifndef WINDOWS + Formula(Formula&& other) = default; + Formula& operator=(Formula&& other) = default; +#endif + + /*! + * Retrieves the name that is associated with this formula. + * + * @return The name that is associated with this formula. + */ + std::string const& getName() const; + + /*! + * Retrieves the expression that is associated with this formula. + * + * @return The expression that is associated with this formula. + */ + storm::expressions::Expression const& getExpression() const; + + /*! + * Retrieves the return type of the formula, i.e., the return-type of the defining expression. + * + * @return The return type of the formula. + */ + storm::expressions::ExpressionReturnType getType() const; + + /*! + * Substitutes all identifiers in the expression of the formula according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting formula. + */ + Formula substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, Formula const& formula); + + private: + // The name of the formula. + std::string name; + + // A predicate that needs to be satisfied by states for the label to be attached. + storm::expressions::Expression expression; + }; + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_FORMULA_H_ */ diff --git a/src/storage/prism/IntegerVariable.cpp b/src/storage/prism/IntegerVariable.cpp new file mode 100644 index 000000000..a80b6394e --- /dev/null +++ b/src/storage/prism/IntegerVariable.cpp @@ -0,0 +1,30 @@ +#include "src/storage/prism/IntegerVariable.h" + +namespace storm { + namespace prism { + IntegerVariable::IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, std::string const& filename, uint_fast64_t lineNumber) : Variable(name, lowerBoundExpression, true, filename, lineNumber), lowerBoundExpression(lowerBoundExpression), upperBoundExpression(upperBoundExpression) { + // Intentionally left empty. + } + + IntegerVariable::IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, storm::expressions::Expression const& initialValueExpression, std::string const& filename, uint_fast64_t lineNumber) : Variable(name, initialValueExpression, false, filename, lineNumber), lowerBoundExpression(lowerBoundExpression), upperBoundExpression(upperBoundExpression) { + // Intentionally left empty. + } + + storm::expressions::Expression const& IntegerVariable::getLowerBoundExpression() const { + return this->lowerBoundExpression; + } + + storm::expressions::Expression const& IntegerVariable::getUpperBoundExpression() const { + return this->upperBoundExpression; + } + + IntegerVariable IntegerVariable::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return IntegerVariable(this->getName(), this->getLowerBoundExpression().substitute<std::map>(substitution), this->getUpperBoundExpression().substitute<std::map>(substitution), this->getInitialValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, IntegerVariable const& variable) { + stream << variable.getName() << ": [" << variable.getLowerBoundExpression() << ".." << variable.getUpperBoundExpression() << "]" << " init " << variable.getInitialValueExpression() << ";"; + return stream; + } + } // namespace prism +} // namespace storm diff --git a/src/storage/prism/IntegerVariable.h b/src/storage/prism/IntegerVariable.h new file mode 100644 index 000000000..a7c069c53 --- /dev/null +++ b/src/storage/prism/IntegerVariable.h @@ -0,0 +1,80 @@ +#ifndef STORM_STORAGE_PRISM_INTEGERVARIABLE_H_ +#define STORM_STORAGE_PRISM_INTEGERVARIABLE_H_ + +#include <map> + +#include "src/storage/prism/Variable.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class IntegerVariable : public Variable { + public: + // Create default implementations of constructors/assignment. + IntegerVariable() = default; + IntegerVariable(IntegerVariable const& other) = default; + IntegerVariable& operator=(IntegerVariable const& other)= default; +#ifndef WINDOWS + IntegerVariable(IntegerVariable&& other) = default; + IntegerVariable& operator=(IntegerVariable&& other) = default; +#endif + + /*! + * Creates an integer variable with the given name and a default initial value. + * + * @param name The name of the variable. + * @param lowerBoundExpression A constant expression defining the lower bound of the domain of the variable. + * @param upperBoundExpression A constant expression defining the upper bound of the domain of the variable. + * @param filename The filename in which the variable is defined. + * @param lineNumber The line number in which the variable is defined. + */ + IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + /*! + * Creates an integer variable with the given name and the given initial value expression. + * + * @param name The name of the variable. + * @param lowerBoundExpression A constant expression defining the lower bound of the domain of the variable. + * @param upperBoundExpression A constant expression defining the upper bound of the domain of the variable. + * @param initialValueExpression A constant expression that defines the initial value of the variable. + * @param filename The filename in which the variable is defined. + * @param lineNumber The line number in which the variable is defined. + */ + IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, storm::expressions::Expression const& initialValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + /*! + * Retrieves an expression defining the lower bound for this integer variable. + * + * @return An expression defining the lower bound for this integer variable. + */ + storm::expressions::Expression const& getLowerBoundExpression() const; + + /*! + * Retrieves an expression defining the upper bound for this integer variable. + * + * @return An expression defining the upper bound for this integer variable. + */ + storm::expressions::Expression const& getUpperBoundExpression() const; + + /*! + * Substitutes all identifiers in the boolean variable according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting boolean variable. + */ + IntegerVariable substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, IntegerVariable const& variable); + + private: + // A constant expression that specifies the lower bound of the domain of the variable. + storm::expressions::Expression lowerBoundExpression; + + // A constant expression that specifies the upper bound of the domain of the variable. + storm::expressions::Expression upperBoundExpression; + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_INTEGERVARIABLE_H_ */ diff --git a/src/storage/prism/Label.cpp b/src/storage/prism/Label.cpp new file mode 100644 index 000000000..a78f9079f --- /dev/null +++ b/src/storage/prism/Label.cpp @@ -0,0 +1,26 @@ +#include "src/storage/prism/Label.h" + +namespace storm { + namespace prism { + Label::Label(std::string const& name, storm::expressions::Expression const& statePredicateExpression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(name), statePredicateExpression(statePredicateExpression) { + // Intentionally left empty. + } + + std::string const& Label::getName() const { + return this->name; + } + + storm::expressions::Expression const& Label::getStatePredicateExpression() const { + return this->statePredicateExpression; + } + + Label Label::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return Label(this->getName(), this->getStatePredicateExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, Label const& label) { + stream << "label \"" << label.getName() << "\" = " << label.getStatePredicateExpression() << ";"; + return stream; + } + } +} \ No newline at end of file diff --git a/src/storage/prism/Label.h b/src/storage/prism/Label.h new file mode 100644 index 000000000..96934adf2 --- /dev/null +++ b/src/storage/prism/Label.h @@ -0,0 +1,68 @@ +#ifndef STORM_STORAGE_PRISM_LABEL_H_ +#define STORM_STORAGE_PRISM_LABEL_H_ + +#include <map> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/expressions/Expression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Label : public LocatedInformation { + public: + /*! + * Creates a label with the given name and state predicate expression. + * + * @param name The name of the label. + * @param statePredicateExpression The predicate that needs to hold before taking a transition with the previously + * specified name in order to obtain the reward. + * @param filename The filename in which the transition reward is defined. + * @param lineNumber The line number in which the transition reward is defined. + */ + Label(std::string const& name, storm::expressions::Expression const& statePredicateExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + Label() = default; + Label(Label const& other) = default; + Label& operator=(Label const& other)= default; +#ifndef WINDOWS + Label(Label&& other) = default; + Label& operator=(Label&& other) = default; +#endif + + /*! + * Retrieves the name that is associated with this label. + * + * @return The name that is associated with this label. + */ + std::string const& getName() const; + + /*! + * Retrieves the state predicate expression that is associated with this label. + * + * @return The state predicate expression that is associated with this label. + */ + storm::expressions::Expression const& getStatePredicateExpression() const; + + /*! + * Substitutes all identifiers in the expression of the label according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting label. + */ + Label substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, Label const& label); + + private: + // The name of the label. + std::string name; + + // A predicate that needs to be satisfied by states for the label to be attached. + storm::expressions::Expression statePredicateExpression; + }; + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_LABEL_H_ */ diff --git a/src/storage/prism/LocatedInformation.cpp b/src/storage/prism/LocatedInformation.cpp new file mode 100644 index 000000000..a5a493319 --- /dev/null +++ b/src/storage/prism/LocatedInformation.cpp @@ -0,0 +1,25 @@ +#include "src/storage/prism/LocatedInformation.h" + +namespace storm { + namespace prism { + LocatedInformation::LocatedInformation(std::string const& filename, uint_fast64_t lineNumber) : filename(filename), lineNumber(lineNumber) { + // Intentionally left empty. + } + + std::string const& LocatedInformation::getFilename() const { + return this->filename; + } + + void LocatedInformation::setFilename(std::string const& filename) { + this->filename = filename; + } + + uint_fast64_t LocatedInformation::getLineNumber() const { + return this->lineNumber; + } + + void LocatedInformation::setLineNumber(uint_fast64_t lineNumber) { + this->lineNumber = lineNumber; + } + } +} \ No newline at end of file diff --git a/src/storage/prism/LocatedInformation.h b/src/storage/prism/LocatedInformation.h new file mode 100644 index 000000000..8aa4d301e --- /dev/null +++ b/src/storage/prism/LocatedInformation.h @@ -0,0 +1,67 @@ +#ifndef STORM_STORAGE_PRISM_LOCATEDINFORMATION_H_ +#define STORM_STORAGE_PRISM_LOCATEDINFORMATION_H_ + +#include <string> + +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class LocatedInformation { + public: + /*! + * Constructs a located information with the given filename and line number. + * + * @param filename The file in which the information was found. + * @param lineNumber The line number in which the information was found. + */ + LocatedInformation(std::string const& filename, uint_fast64_t lineNumber); + + // Create default implementations of constructors/assignment. + LocatedInformation() = default; + LocatedInformation(LocatedInformation const& other) = default; + LocatedInformation& operator=(LocatedInformation const& other)= default; +#ifndef WINDOWS + LocatedInformation(LocatedInformation&& other) = default; + LocatedInformation& operator=(LocatedInformation&& other) = default; +#endif + + /*! + * Retrieves the name of the file in which the information was found. + * + * @return The name of the file in which the information was found. + */ + std::string const& getFilename() const; + + /*! + * Sets the filename of this information. + * + * @param filename The new filename of this information. + */ + void setFilename(std::string const& filename); + + /*! + * Retrieves the line number in which the information was found. + * + * @return The line number in which the information was found. + */ + uint_fast64_t getLineNumber() const; + + /*! + * Sets the line number of this information. + * + * @param lineNumber The new line number for this information. + */ + void setLineNumber(uint_fast64_t lineNumber); + + private: + // The file in which the piece of information was found. + std::string filename; + + // The line in the file in which the piece of information was found. + uint_fast64_t lineNumber; + }; + } +} + +#endif /* STORM_STORAGE_PRISM_LOCATEDINFORMATION_H_ */ \ No newline at end of file diff --git a/src/storage/prism/Module.cpp b/src/storage/prism/Module.cpp new file mode 100644 index 000000000..f17e1bc12 --- /dev/null +++ b/src/storage/prism/Module.cpp @@ -0,0 +1,169 @@ +#include "src/storage/prism/Module.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/OutOfRangeException.h" +#include "src/exceptions/InvalidArgumentException.h" + +namespace storm { + namespace prism { + Module::Module(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), moduleName(moduleName), booleanVariables(booleanVariables), booleanVariableToIndexMap(), integerVariables(integerVariables), integerVariableToIndexMap(), commands(commands), actions(), actionsToCommandIndexMap() { + // Initialize the internal mappings for fast information retrieval. + this->createMappings(); + } + + std::size_t Module::getNumberOfBooleanVariables() const { + return this->booleanVariables.size(); + } + + std::size_t Module::getNumberOfIntegerVariables() const { + return this->integerVariables.size(); + } + + storm::prism::BooleanVariable const& Module::getBooleanVariable(std::string const& variableName) const { + auto const& nameIndexPair = this->booleanVariableToIndexMap.find(variableName); + LOG_THROW(nameIndexPair != this->booleanVariableToIndexMap.end(), storm::exceptions::InvalidArgumentException, "Unknown boolean variable '" << variableName << "'."); + return this->getBooleanVariables()[nameIndexPair->second]; + } + + std::vector<storm::prism::BooleanVariable> const& Module::getBooleanVariables() const { + return this->booleanVariables; + } + + storm::prism::IntegerVariable const& Module::getIntegerVariable(std::string const& variableName) const { + auto const& nameIndexPair = this->integerVariableToIndexMap.find(variableName); + LOG_THROW(nameIndexPair != this->integerVariableToIndexMap.end(), storm::exceptions::InvalidArgumentException, "Unknown integer variable '" << variableName << "'."); + return this->getIntegerVariables()[nameIndexPair->second]; + } + + std::vector<storm::prism::IntegerVariable> const& Module::getIntegerVariables() const { + return this->integerVariables; + } + + std::size_t Module::getNumberOfCommands() const { + return this->commands.size(); + } + + std::size_t Module::getNumberOfUpdates() const { + std::size_t result = 0; + for (auto const& command : this->getCommands()) { + result += command.getNumberOfUpdates(); + } + return result; + } + + storm::prism::Command const& Module::getCommand(uint_fast64_t index) const { + return this->commands[index]; + } + + std::vector<storm::prism::Command> const& Module::getCommands() const { + return this->commands; + } + + std::string const& Module::getName() const { + return this->moduleName; + } + + std::set<std::string> const& Module::getActions() const { + return this->actions; + } + + bool Module::hasAction(std::string const& action) const { + auto const& actionEntry = this->actions.find(action); + return actionEntry != this->actions.end(); + } + + std::set<uint_fast64_t> const& Module::getCommandIndicesByAction(std::string const& action) const { + auto actionsCommandSetPair = this->actionsToCommandIndexMap.find(action); + if (actionsCommandSetPair != this->actionsToCommandIndexMap.end()) { + return actionsCommandSetPair->second; + } + + LOG_THROW(false, storm::exceptions::OutOfRangeException, "Action name '" << action << "' does not exist in module."); + } + + void Module::createMappings() { + // Clear the current mappings. + this->actionsToCommandIndexMap.clear(); + this->booleanVariableToIndexMap.clear(); + this->integerVariableToIndexMap.clear(); + + // Create the mappings for the variables. + for (uint_fast64_t i = 0; i < this->booleanVariables.size(); ++i) { + this->booleanVariableToIndexMap[this->getBooleanVariables()[i].getName()] = i; + } + for (uint_fast64_t i = 0; i < this->integerVariables.size(); ++i) { + this->integerVariableToIndexMap[this->getIntegerVariables()[i].getName()] = i; + } + + // Add the mapping for all commands. + for (uint_fast64_t i = 0; i < this->commands.size(); i++) { + std::string const& action = this->commands[i].getActionName(); + if (action != "") { + if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) { + this->actionsToCommandIndexMap.emplace(action, std::set<uint_fast64_t>()); + } + this->actionsToCommandIndexMap[action].insert(i); + this->actions.insert(action); + } + } + + // For all actions that are "in the module", but for which no command exists, we add the mapping to an empty + // set of commands. + for (auto const& action : this->actions) { + if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) { + this->actionsToCommandIndexMap[action] = std::set<uint_fast64_t>(); + } + } + } + + Module Module::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const { + // First construct the new vector of commands. + std::vector<storm::prism::Command> newCommands; + for (auto const& command : commands) { + if (indexSet.find(command.getGlobalIndex()) != indexSet.end()) { + newCommands.push_back(command); + } + } + + return Module(this->getName(), this->getBooleanVariables(), this->getIntegerVariables(), newCommands); + } + + Module Module::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + std::vector<BooleanVariable> newBooleanVariables; + newBooleanVariables.reserve(this->getNumberOfBooleanVariables()); + for (auto const& booleanVariable : this->getBooleanVariables()) { + newBooleanVariables.emplace_back(booleanVariable.substitute(substitution)); + } + + std::vector<IntegerVariable> newIntegerVariables; + newBooleanVariables.reserve(this->getNumberOfIntegerVariables()); + for (auto const& integerVariable : this->getIntegerVariables()) { + newIntegerVariables.emplace_back(integerVariable.substitute(substitution)); + } + + std::vector<Command> newCommands; + newCommands.reserve(this->getNumberOfCommands()); + for (auto const& command : this->getCommands()) { + newCommands.emplace_back(command.substitute(substitution)); + } + + return Module(this->getName(), newBooleanVariables, newIntegerVariables, newCommands, this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, Module const& module) { + stream << "module " << module.getName() << std::endl; + for (auto const& booleanVariable : module.getBooleanVariables()) { + stream << "\t" << booleanVariable << std::endl; + } + for (auto const& integerVariable : module.getIntegerVariables()) { + stream << "\t" << integerVariable << std::endl; + } + for (auto const& command : module.getCommands()) { + stream << "\t" << command << std::endl; + } + stream << "endmodule" << std::endl; + return stream; + } + + + } // namespace ir +} // namespace storm diff --git a/src/storage/prism/Module.h b/src/storage/prism/Module.h new file mode 100644 index 000000000..f4fd21f29 --- /dev/null +++ b/src/storage/prism/Module.h @@ -0,0 +1,196 @@ +#ifndef STORM_STORAGE_PRISM_MODULE_H_ +#define STORM_STORAGE_PRISM_MODULE_H_ + +#include <set> +#include <string> +#include <vector> +#include <memory> +#include <boost/container/flat_set.hpp> + +#include "src/storage/prism/BooleanVariable.h" +#include "src/storage/prism/IntegerVariable.h" +#include "src/storage/prism/Command.h" +#include "src/storage/expressions/VariableExpression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Module : public LocatedInformation { + public: + /*! + * Creates a module with the given name, variables and commands. + * + * @param moduleName The name of the module. + * @param booleanVariables The boolean variables defined by the module. + * @param integerVariables The integer variables defined by the module. + * @param commands The commands of the module. + * @param filename The filename in which the module is defined. + * @param lineNumber The line number in which the module is defined. + */ + Module(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + Module() = default; + Module(Module const& other) = default; + Module& operator=(Module const& other)= default; +#ifndef WINDOWS + Module(Module&& other) = default; + Module& operator=(Module&& other) = default; +#endif + + /*! + * Retrieves the number of boolean variables in the module. + * + * @return the number of boolean variables in the module. + */ + std::size_t getNumberOfBooleanVariables() const; + + /*! + * Retrieves the number of integer variables in the module. + * + * @return The number of integer variables in the module. + */ + std::size_t getNumberOfIntegerVariables() const; + + /*! + * Retrieves a reference to the boolean variable with the given name. + * + * @param variableName The name of the boolean variable to retrieve. + * @return A reference to the boolean variable with the given name. + */ + storm::prism::BooleanVariable const& getBooleanVariable(std::string const& variableName) const; + + /*! + * Retrieves the boolean variables of the module. + * + * @return The boolean variables of the module. + */ + std::vector<storm::prism::BooleanVariable> const& getBooleanVariables() const; + + /*! + * Retrieves a reference to the integer variable with the given name. + * + * @param variableName The name of the integer variable to retrieve. + * @return A reference to the integer variable with the given name. + */ + storm::prism::IntegerVariable const& getIntegerVariable(std::string const& variableName) const; + + /*! + * Retrieves the integer variables of the module. + * + * @return The integer variables of the module. + */ + std::vector<storm::prism::IntegerVariable> const& getIntegerVariables() const; + + /*! + * Retrieves the number of commands of this module. + * + * @return The number of commands of this module. + */ + std::size_t getNumberOfCommands() const; + + /*! + * Retrieves the total number of updates of this module. + * + * @return The total number of updates of this module. + */ + std::size_t getNumberOfUpdates() const; + + /*! + * Retrieves a reference to the command with the given index. + * + * @param index The index of the command to retrieve. + * @return A reference to the command with the given index. + */ + storm::prism::Command const& getCommand(uint_fast64_t index) const; + + /*! + * Retrieves the commands of the module. + * + * @return The commands of the module. + */ + std::vector<storm::prism::Command> const& getCommands() const; + + /*! + * Retrieves the name of the module. + * + * @return The name of the module. + */ + std::string const& getName() const; + + /*! + * Retrieves the set of actions present in this module. + * + * @return the set of actions present in this module. + */ + std::set<std::string> const& getActions() const; + + /*! + * Retrieves whether or not this module contains a command labeled with the given action. + * + * @param action The action name to look for in this module. + * @return True iff the module has at least one command labeled with the given action. + */ + bool hasAction(std::string const& action) const; + + /*! + * Retrieves the indices of all commands within this module that are labelled by the given action. + * + * @param action The action with which the commands have to be labelled. + * @return A set of indices of commands that are labelled with the given action. + */ + std::set<uint_fast64_t> const& getCommandIndicesByAction(std::string const& action) const; + + /*! + * Creates a new module that drops all commands whose indices are not in the given set. + * + * @param indexSet The set of indices for which to keep the commands. + * @return The module resulting from erasing all commands whose indices are not in the given set. + */ + Module restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const; + + /*! + * Substitutes all identifiers in the module according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting module. + */ + Module substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, Module const& module); + + private: + /*! + * Computes the locally maintained mappings for fast data retrieval. + */ + void createMappings(); + + // The name of the module. + std::string moduleName; + + // A list of boolean variables. + std::vector<storm::prism::BooleanVariable> booleanVariables; + + // A mapping from boolean variables to the corresponding indices in the vector. + std::map<std::string, uint_fast64_t> booleanVariableToIndexMap; + + // A list of integer variables. + std::vector<storm::prism::IntegerVariable> integerVariables; + + // A mapping from integer variables to the corresponding indices in the vector. + std::map<std::string, uint_fast64_t> integerVariableToIndexMap; + + // The commands associated with the module. + std::vector<storm::prism::Command> commands; + + // The set of actions present in this module. + std::set<std::string> actions; + + // A map of actions to the set of commands labeled with this action. + std::map<std::string, std::set<uint_fast64_t>> actionsToCommandIndexMap; + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_MODULE_H_ */ diff --git a/src/storage/prism/Program.cpp b/src/storage/prism/Program.cpp new file mode 100644 index 000000000..cdbba3e22 --- /dev/null +++ b/src/storage/prism/Program.cpp @@ -0,0 +1,365 @@ +#include "src/storage/prism/Program.h" +#include "src/exceptions/ExceptionMacros.h" +#include "exceptions/InvalidArgumentException.h" +#include "src/exceptions/OutOfRangeException.h" + +namespace storm { + namespace prism { + Program::Program(ModelType modelType, std::vector<Constant> const& constants, std::vector<BooleanVariable> const& globalBooleanVariables, std::vector<IntegerVariable> const& globalIntegerVariables, std::vector<Formula> const& formulas, std::vector<Module> const& modules, std::vector<RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::vector<Label> const& labels, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), modelType(modelType), constants(constants), constantToIndexMap(), globalBooleanVariables(globalBooleanVariables), globalBooleanVariableToIndexMap(), globalIntegerVariables(globalIntegerVariables), globalIntegerVariableToIndexMap(), formulas(formulas), formulaToIndexMap(), modules(modules), moduleToIndexMap(), rewardModels(rewardModels), rewardModelToIndexMap(), hasInitialStatesExpression(hasInitialStatesExpression), initialStatesExpression(initialStatesExpression), labels(labels), labelToIndexMap(), actions(), actionsToModuleIndexMap(), variableToModuleIndexMap() { + this->createMappings(); + } + + Program::ModelType Program::getModelType() const { + return modelType; + } + + bool Program::hasUndefinedConstants() const { + for (auto const& constant : this->getConstants()) { + if (!constant.isDefined()) { + return true; + } + } + return false; + } + + bool Program::hasConstant(std::string const& constantName) const { + return this->constantToIndexMap.find(constantName) != this->constantToIndexMap.end(); + } + + Constant const& Program::getConstant(std::string const& constantName) const { + auto const& constantIndexPair = this->constantToIndexMap.find(constantName); + return this->getConstants()[constantIndexPair->second]; + } + + std::vector<Constant> const& Program::getConstants() const { + return this->constants; + } + + std::size_t Program::getNumberOfConstants() const { + return this->getConstants().size(); + } + + std::vector<BooleanVariable> const& Program::getGlobalBooleanVariables() const { + return this->globalBooleanVariables; + } + + std::vector<IntegerVariable> const& Program::getGlobalIntegerVariables() const { + return this->globalIntegerVariables; + } + + BooleanVariable const& Program::getGlobalBooleanVariable(std::string const& variableName) const { + auto const& nameIndexPair = this->globalBooleanVariableToIndexMap.find(variableName); + LOG_THROW(nameIndexPair != this->globalBooleanVariableToIndexMap.end(), storm::exceptions::OutOfRangeException, "Unknown boolean variable '" << variableName << "'."); + return this->getGlobalBooleanVariables()[nameIndexPair->second]; + } + + IntegerVariable const& Program::getGlobalIntegerVariable(std::string const& variableName) const { + auto const& nameIndexPair = this->globalIntegerVariableToIndexMap.find(variableName); + LOG_THROW(nameIndexPair != this->globalIntegerVariableToIndexMap.end(), storm::exceptions::OutOfRangeException, "Unknown integer variable '" << variableName << "'."); + return this->getGlobalIntegerVariables()[nameIndexPair->second]; + } + + std::size_t Program::getNumberOfGlobalBooleanVariables() const { + return this->getGlobalBooleanVariables().size(); + } + + std::size_t Program::getNumberOfGlobalIntegerVariables() const { + return this->getGlobalIntegerVariables().size(); + } + + std::vector<Formula> const& Program::getFormulas() const { + return this->formulas; + } + + std::size_t Program::getNumberOfFormulas() const { + return this->getFormulas().size(); + } + + std::size_t Program::getNumberOfModules() const { + return this->getModules().size(); + } + + storm::prism::Module const& Program::getModule(uint_fast64_t index) const { + return this->modules[index]; + } + + Module const& Program::getModule(std::string const& moduleName) const { + auto const& nameIndexPair = this->moduleToIndexMap.find(moduleName); + LOG_THROW(nameIndexPair != this->moduleToIndexMap.end(), storm::exceptions::OutOfRangeException, "Unknown module '" << moduleName << "'."); + return this->getModules()[nameIndexPair->second]; + } + + std::vector<storm::prism::Module> const& Program::getModules() const { + return this->modules; + } + + bool Program::definesInitialStatesExpression() const { + return this->hasInitialStatesExpression; + } + + storm::expressions::Expression Program::getInitialStatesExpression() const { + // If the program specifies the initial states explicitly, we simply return the expression. + if (this->definesInitialStatesExpression()) { + return this->initialStatesExpression; + } else { + // Otherwise, we need to assert that all variables are equal to their initial value. + storm::expressions::Expression result = storm::expressions::Expression::createTrue(); + + for (auto const& module : this->getModules()) { + for (auto const& booleanVariable : module.getBooleanVariables()) { + result = result && (storm::expressions::Expression::createBooleanVariable(booleanVariable.getName()).iff(booleanVariable.getInitialValueExpression())); + } + for (auto const& integerVariable : module.getIntegerVariables()) { + result = result && (storm::expressions::Expression::createIntegerVariable(integerVariable.getName()) == integerVariable.getInitialValueExpression()); + } + } + return result; + } + } + + std::set<std::string> const& Program::getActions() const { + return this->actions; + } + + std::set<uint_fast64_t> const& Program::getModuleIndicesByAction(std::string const& action) const { + auto const& actionModuleSetPair = this->actionsToModuleIndexMap.find(action); + LOG_THROW(actionModuleSetPair != this->actionsToModuleIndexMap.end(), storm::exceptions::OutOfRangeException, "Action name '" << action << "' does not exist."); + return actionModuleSetPair->second; + } + + uint_fast64_t Program::getModuleIndexByVariable(std::string const& variableName) const { + auto const& variableNameToModuleIndexPair = this->variableToModuleIndexMap.find(variableName); + LOG_THROW(variableNameToModuleIndexPair != this->variableToModuleIndexMap.end(), storm::exceptions::OutOfRangeException, "Variable '" << variableName << "' does not exist."); + return variableNameToModuleIndexPair->second; + } + + std::vector<storm::prism::RewardModel> const& Program::getRewardModels() const { + return this->rewardModels; + } + + std::size_t Program::getNumberOfRewardModels() const { + return this->getRewardModels().size(); + } + + storm::prism::RewardModel const& Program::getRewardModel(std::string const& name) const { + auto const& nameIndexPair = this->rewardModelToIndexMap.find(name); + LOG_THROW(nameIndexPair != this->rewardModelToIndexMap.end(), storm::exceptions::OutOfRangeException, "Reward model '" << name << "' does not exist."); + return this->getRewardModels()[nameIndexPair->second]; + } + + std::vector<Label> const& Program::getLabels() const { + return this->labels; + } + + std::size_t Program::getNumberOfLabels() const { + return this->getLabels().size(); + } + + Program Program::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const { + std::vector<storm::prism::Module> newModules; + newModules.reserve(this->getNumberOfModules()); + + for (auto const& module : this->getModules()) { + newModules.push_back(module.restrictCommands(indexSet)); + } + + return Program(this->getModelType(), this->getConstants(), this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), newModules, this->getRewardModels(), this->definesInitialStatesExpression(), this->getInitialStatesExpression(), this->getLabels()); + } + + void Program::createMappings() { + // Build the mappings for constants, global variables, formulas, modules, reward models and labels. + for (uint_fast64_t constantIndex = 0; constantIndex < this->getNumberOfConstants(); ++constantIndex) { + this->constantToIndexMap[this->getConstants()[constantIndex].getName()] = constantIndex; + } + for (uint_fast64_t globalVariableIndex = 0; globalVariableIndex < this->getNumberOfGlobalBooleanVariables(); ++globalVariableIndex) { + this->globalBooleanVariableToIndexMap[this->getGlobalBooleanVariables()[globalVariableIndex].getName()] = globalVariableIndex; + } + for (uint_fast64_t globalVariableIndex = 0; globalVariableIndex < this->getNumberOfGlobalIntegerVariables(); ++globalVariableIndex) { + this->globalIntegerVariableToIndexMap[this->getGlobalIntegerVariables()[globalVariableIndex].getName()] = globalVariableIndex; + } + for (uint_fast64_t formulaIndex = 0; formulaIndex < this->getNumberOfFormulas(); ++formulaIndex) { + this->formulaToIndexMap[this->getFormulas()[formulaIndex].getName()] = formulaIndex; + } + for (uint_fast64_t moduleIndex = 0; moduleIndex < this->getNumberOfModules(); ++moduleIndex) { + this->moduleToIndexMap[this->getModules()[moduleIndex].getName()] = moduleIndex; + } + for (uint_fast64_t rewardModelIndex = 0; rewardModelIndex < this->getNumberOfRewardModels(); ++rewardModelIndex) { + this->rewardModelToIndexMap[this->getRewardModels()[rewardModelIndex].getName()] = rewardModelIndex; + } + for (uint_fast64_t labelIndex = 0; labelIndex < this->getNumberOfLabels(); ++labelIndex) { + this->labelToIndexMap[this->getLabels()[labelIndex].getName()] = labelIndex; + } + + // Build the mapping from action names to module indices so that the lookup can later be performed quickly. + for (unsigned int moduleIndex = 0; moduleIndex < this->getNumberOfModules(); moduleIndex++) { + Module const& module = this->getModule(moduleIndex); + + for (auto const& action : module.getActions()) { + auto const& actionModuleIndicesPair = this->actionsToModuleIndexMap.find(action); + if (actionModuleIndicesPair == this->actionsToModuleIndexMap.end()) { + this->actionsToModuleIndexMap[action] = std::set<uint_fast64_t>(); + } + this->actionsToModuleIndexMap[action].insert(moduleIndex); + this->actions.insert(action); + } + + // Put in the appropriate entries for the mapping from variable names to module index. + for (auto const& booleanVariable : module.getBooleanVariables()) { + this->variableToModuleIndexMap[booleanVariable.getName()] = moduleIndex; + } + for (auto const& integerVariable : module.getBooleanVariables()) { + this->variableToModuleIndexMap[integerVariable.getName()] = moduleIndex; + } + } + + } + + Program Program::defineUndefinedConstants(std::map<std::string, storm::expressions::Expression> const& constantDefinitions) const { + // For sanity checking, we keep track of all undefined constants that we define in the course of this + // procedure. + std::set<std::string> definedUndefinedConstants; + + std::vector<Constant> newConstants; + newConstants.reserve(this->getNumberOfConstants()); + for (auto const& constant : this->getConstants()) { + // If the constant is already defined, we need to replace the appearances of undefined constants in its + // defining expression + if (constant.isDefined()) { + // Make sure we are not trying to define an already defined constant. + LOG_THROW(constantDefinitions.find(constant.getName()) == constantDefinitions.end(), storm::exceptions::InvalidArgumentException, "Illegally defining already defined constant '" << constant.getName() << "'."); + + // Now replace the occurrences of undefined constants in its defining expression. + newConstants.emplace_back(constant.getType(), constant.getName(), constant.getExpression().substitute<std::map>(constantDefinitions), constant.getFilename(), constant.getLineNumber()); + } else { + auto const& variableExpressionPair = constantDefinitions.find(constant.getName()); + + // If the constant is not defined by the mapping, we leave it like it is. + if (variableExpressionPair == constantDefinitions.end()) { + newConstants.emplace_back(constant); + } else { + // Otherwise, we add it to the defined constants and assign it the appropriate expression. + definedUndefinedConstants.insert(constant.getName()); + + // Make sure the type of the constant is correct. + LOG_THROW(variableExpressionPair->second.getReturnType() == constant.getType(), storm::exceptions::InvalidArgumentException, "Illegal type of expression defining constant '" << constant.getName() << "'."); + + // Now create the defined constant. + newConstants.emplace_back(constant.getType(), constant.getName(), variableExpressionPair->second, constant.getFilename(), constant.getLineNumber()); + } + } + } + + // As a sanity check, we make sure that the given mapping does not contain any definitions for identifiers + // that are not undefined constants. + for (auto const& constantExpressionPair : constantDefinitions) { + LOG_THROW(definedUndefinedConstants.find(constantExpressionPair.first) != definedUndefinedConstants.end(), storm::exceptions::InvalidArgumentException, "Unable to define non-existant constant."); + } + + return Program(this->getModelType(), newConstants, this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), this->getModules(), this->getRewardModels(), this->definesInitialStatesExpression(), this->getInitialStatesExpression(), this->getLabels()); + } + + Program Program::substituteConstants() const { + // We start by creating the appropriate substitution + std::map<std::string, storm::expressions::Expression> constantSubstitution; + std::vector<Constant> newConstants(this->getConstants()); + for (uint_fast64_t constantIndex = 0; constantIndex < newConstants.size(); ++constantIndex) { + auto const& constant = newConstants[constantIndex]; + LOG_THROW(constant.isDefined(), storm::exceptions::InvalidArgumentException, "Cannot substitute constants in program that contains undefined constants."); + + // Put the corresponding expression in the substitution. + constantSubstitution.emplace(constant.getName(), constant.getExpression()); + + // If there is at least one more constant to come, we substitute the costants we have so far. + if (constantIndex + 1 < newConstants.size()) { + newConstants[constantIndex + 1] = newConstants[constantIndex + 1].substitute(constantSubstitution); + } + } + + // Now we can substitute the constants in all expressions appearing in the program. + std::vector<BooleanVariable> newBooleanVariables; + newBooleanVariables.reserve(this->getNumberOfGlobalBooleanVariables()); + for (auto const& booleanVariable : this->getGlobalBooleanVariables()) { + newBooleanVariables.emplace_back(booleanVariable.substitute(constantSubstitution)); + } + + std::vector<IntegerVariable> newIntegerVariables; + newBooleanVariables.reserve(this->getNumberOfGlobalIntegerVariables()); + for (auto const& integerVariable : this->getGlobalIntegerVariables()) { + newIntegerVariables.emplace_back(integerVariable.substitute(constantSubstitution)); + } + + std::vector<Formula> newFormulas; + newFormulas.reserve(this->getNumberOfFormulas()); + for (auto const& formula : this->getFormulas()) { + newFormulas.emplace_back(formula.substitute(constantSubstitution)); + } + + std::vector<Module> newModules; + newModules.reserve(this->getNumberOfModules()); + for (auto const& module : this->getModules()) { + newModules.emplace_back(module.substitute(constantSubstitution)); + } + + std::vector<RewardModel> newRewardModels; + newRewardModels.reserve(this->getNumberOfRewardModels()); + for (auto const& rewardModel : this->getRewardModels()) { + newRewardModels.emplace_back(rewardModel.substitute(constantSubstitution)); + } + + storm::expressions::Expression newInitialStateExpression = this->getInitialStatesExpression().substitute<std::map>(constantSubstitution); + + std::vector<Label> newLabels; + newLabels.reserve(this->getNumberOfLabels()); + for (auto const& label : this->getLabels()) { + newLabels.emplace_back(label.substitute(constantSubstitution)); + } + + return Program(this->getModelType(), newConstants, newBooleanVariables, newIntegerVariables, newFormulas, newModules, newRewardModels, this->definesInitialStatesExpression(), newInitialStateExpression, newLabels); + } + + std::ostream& operator<<(std::ostream& stream, Program const& program) { + switch (program.getModelType()) { + case Program::ModelType::UNDEFINED: stream << "undefined"; break; + case Program::ModelType::DTMC: stream << "dtmc"; break; + case Program::ModelType::CTMC: stream << "ctmc"; break; + case Program::ModelType::MDP: stream << "mdp"; break; + case Program::ModelType::CTMDP: stream << "ctmdp"; break; + case Program::ModelType::MA: stream << "ma"; break; + } + stream << std::endl; + + for (auto const& constant : program.getConstants()) { + stream << constant << std::endl; + } + stream << std::endl; + + for (auto const& variable : program.getGlobalBooleanVariables()) { + stream << "global " << variable << std::endl; + } + for (auto const& variable : program.getGlobalIntegerVariables()) { + stream << "global " << variable << std::endl; + } + stream << std::endl; + + for (auto const& formula : program.getFormulas()) { + stream << formula << std::endl; + } + stream << std::endl; + + for (auto const& module : program.getModules()) { + stream << module << std::endl; + } + + for (auto const& rewardModel : program.getRewardModels()) { + stream << rewardModel << std::endl; + } + + for (auto const& label : program.getLabels()) { + stream << label << std::endl; + } + + return stream; + } + + } // namespace ir +} // namepsace storm diff --git a/src/storage/prism/Program.h b/src/storage/prism/Program.h new file mode 100644 index 000000000..40f8047e1 --- /dev/null +++ b/src/storage/prism/Program.h @@ -0,0 +1,359 @@ +#ifndef STORM_STORAGE_PRISM_PROGRAM_H_ +#define STORM_STORAGE_PRISM_PROGRAM_H_ + +#include <map> +#include <vector> +#include <set> +#include <boost/container/flat_set.hpp> + +#include "src/storage/expressions/Expression.h" +#include "src/storage/prism/Constant.h" +#include "src/storage/prism/Formula.h" +#include "src/storage/prism/Label.h" +#include "src/storage/prism/Module.h" +#include "src/storage/prism/RewardModel.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Program : public LocatedInformation { + public: + /*! + * An enum for the different model types. + */ + enum class ModelType {UNDEFINED, DTMC, CTMC, MDP, CTMDP, MA}; + + /*! + * Creates a program with the given model type, undefined constants, global variables, modules, reward + * models, labels and initial states. + * + * @param modelType The type of the program. + * @param constants The constants of the program. + * @param globalBooleanVariables The global boolean variables of the program. + * @param globalIntegerVariables The global integer variables of the program. + * @param formulas The formulas defined in the program. + * @param modules The modules of the program. + * @param hasInitialStatesExpression A flag indicating whether the program specifies its initial states via + * an explicit initial construct. + * @param initialStatesExpression If the model specifies an explicit initial construct, this + * expression defines its initial states. Otherwise it is irrelevant and may be set to an arbitrary (but + * valid) expression, e.g. false. + * @param rewardModels The reward models of the program. + * @param labels The labels defined for this program. + * @param filename The filename in which the program is defined. + * @param lineNumber The line number in which the program is defined. + */ + Program(ModelType modelType, std::vector<Constant> const& constants, std::vector<BooleanVariable> const& globalBooleanVariables, std::vector<IntegerVariable> const& globalIntegerVariables, std::vector<Formula> const& formulas, std::vector<Module> const& modules, std::vector<RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::vector<Label> const& labels, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Provide default implementations for constructors and assignments. + Program() = default; + Program(Program const& other) = default; + Program& operator=(Program const& other) = default; +#ifndef WINDOWS + Program(Program&& other) = default; + Program& operator=(Program&& other) = default; +#endif + + /*! + * Retrieves the model type of the model. + * + * @return The type of the model. + */ + ModelType getModelType() const; + + /*! + * Retrieves whether there are undefined constants of any type in the program. + * + * @return True iff there are undefined constants of any type in the program. + */ + bool hasUndefinedConstants() const; + + /*! + * Retrieves whether the given constant exists in the program. + * + * @param constantName The name of the constant to search. + * @return True iff the constant exists in the program. + */ + bool hasConstant(std::string const& constantName) const; + + /*! + * Retrieves the constant with the given name if it exists. + * + * @param constantName The name of the constant to retrieve. + * @return The constant with the given name if it exists. + */ + Constant const& getConstant(std::string const& constantName) const; + + /*! + * Retrieves all constants defined in the program. + * + * @return The constants defined in the program. + */ + std::vector<Constant> const& getConstants() const; + + /*! + * Retrieves the number of all constants defined in the program. + * + * @return The number of constants defined in the program. + */ + std::size_t getNumberOfConstants() const; + + /*! + * Retrieves the global boolean variables of the program. + * + * @return The global boolean variables of the program. + */ + std::vector<BooleanVariable> const& getGlobalBooleanVariables() const; + + /*! + * Retrieves a the global boolean variable with the given name. + * + * @param variableName The name of the global boolean variable to retrieve. + * @return The global boolean variable with the given name. + */ + BooleanVariable const& getGlobalBooleanVariable(std::string const& variableName) const; + + /*! + * Retrieves the global integer variables of the program. + * + * @return The global integer variables of the program. + */ + std::vector<IntegerVariable> const& getGlobalIntegerVariables() const; + + /*! + * Retrieves a the global integer variable with the given name. + * + * @param variableName The name of the global integer variable to retrieve. + * @return The global integer variable with the given name. + */ + IntegerVariable const& getGlobalIntegerVariable(std::string const& variableName) const; + + /*! + * Retrieves the number of global boolean variables of the program. + * + * @return The number of global boolean variables of the program. + */ + std::size_t getNumberOfGlobalBooleanVariables() const; + + /*! + * Retrieves the number of global integer variables of the program. + * + * @return The number of global integer variables of the program. + */ + std::size_t getNumberOfGlobalIntegerVariables() const; + + /*! + * Retrieves the formulas defined in the program. + * + * @return The formulas defined in the program. + */ + std::vector<Formula> const& getFormulas() const; + + /*! + * Retrieves the number of formulas in the program. + * + * @return The number of formulas in the program. + */ + std::size_t getNumberOfFormulas() const; + + /*! + * Retrieves the number of modules in the program. + * + * @return The number of modules in the program. + */ + std::size_t getNumberOfModules() const; + + /*! + * Retrieves the module with the given index. + * + * @param index The index of the module to retrieve. + * @return The module with the given index. + */ + Module const& getModule(uint_fast64_t index) const; + + /*! + * Retrieves the module with the given name. + * + * @param moduleName The name of the module to retrieve. + * @return The module with the given name. + */ + Module const& getModule(std::string const& moduleName) const; + + /*! + * Retrieves all modules of the program. + * + * @return All modules of the program. + */ + std::vector<Module> const& getModules() const; + + /*! + * Retrieves whether the program explicitly specifies an expression characterizing the initial states. + * + * @return True iff the program specifies an expression defining the initial states. + */ + bool definesInitialStatesExpression() const; + + /*! + * Retrieves an expression characterizing the initial states of the program. + * + * @return An expression characterizing the initial states. + */ + storm::expressions::Expression getInitialStatesExpression() const; + + /*! + * Retrieves the set of actions present in the program. + * + * @return The set of actions present in the program. + */ + std::set<std::string> const& getActions() const; + + /*! + * Retrieves the indices of all modules within this program that contain commands that are labelled with the + * given action. + * + * @param action The name of the action the modules are supposed to possess. + * @return A set of indices of all matching modules. + */ + std::set<uint_fast64_t> const& getModuleIndicesByAction(std::string const& action) const; + + /*! + * Retrieves the index of the module in which the given variable name was declared. + * + * @param variableName The name of the variable to search. + * @return The index of the module in which the given variable name was declared. + */ + uint_fast64_t getModuleIndexByVariable(std::string const& variableName) const; + + /*! + * Retrieves the reward models of the program. + * + * @return The reward models of the program. + */ + std::vector<RewardModel> const& getRewardModels() const; + + /*! + * Retrieves the number of reward models in the program. + * + * @return The number of reward models in the program. + */ + std::size_t getNumberOfRewardModels() const; + + /*! + * Retrieves the reward model with the given name. + * + * @param rewardModelName The name of the reward model to return. + * @return The reward model with the given name. + */ + RewardModel const& getRewardModel(std::string const& rewardModelName) const; + + /*! + * Retrieves all labels that are defined by the probabilitic program. + * + * @return A set of labels that are defined in the program. + */ + std::vector<Label> const& getLabels() const; + + /*! + * Retrieves the number of labels in the program. + * + * @return The number of labels in the program. + */ + std::size_t getNumberOfLabels() const; + + /*! + * Creates a new program that drops all commands whose indices are not in the given set. + * + * @param indexSet The set of indices for which to keep the commands. + */ + Program restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const; + + /*! + * Defines the undefined constants according to the given map and returns the resulting program. + * + * @param constantDefinitions A mapping from undefined constant names to the expressions they are supposed + * to be replaced with. + * @return The program after all undefined constants in the given map have been replaced with their + * definitions. + */ + Program defineUndefinedConstants(std::map<std::string, storm::expressions::Expression> const& constantDefinitions) const; + + /*! + * Substitutes all constants appearing in the expressions of the program by their defining expressions. For + * this to work, all constants need to be defined prior to calling this. + * + * @return The resulting program that only contains expressions over variables of the program. + */ + Program substituteConstants() const; + + friend std::ostream& operator<<(std::ostream& stream, Program const& program); + + private: + // Creates the internal mappings. + void createMappings(); + + // The type of the model. + ModelType modelType; + + // The undefined constants of the program. + std::vector<Constant> constants; + + // A mapping from constant names to their corresponding indices. + std::map<std::string, uint_fast64_t> constantToIndexMap; + + // The global boolean variables. + std::vector<BooleanVariable> globalBooleanVariables; + + // A mapping from global boolean variable names to their corresponding indices. + std::map<std::string, uint_fast64_t> globalBooleanVariableToIndexMap; + + // The global integer variables. + std::vector<IntegerVariable> globalIntegerVariables; + + // A mapping from global integer variable names to their corresponding indices. + std::map<std::string, uint_fast64_t> globalIntegerVariableToIndexMap; + + // The formulas defined in the program. + std::vector<Formula> formulas; + + // A mapping of formula names to their corresponding indices. + std::map<std::string, uint_fast64_t> formulaToIndexMap; + + // The modules associated with the program. + std::vector<Module> modules; + + // A mapping of module names to their indices. + std::map<std::string, uint_fast64_t> moduleToIndexMap; + + // The reward models associated with the program. + std::vector<RewardModel> rewardModels; + + // A mapping of reward models to their indices. + std::map<std::string, uint_fast64_t> rewardModelToIndexMap; + + // A flag that indicates whether the initial states of the program were given explicitly (in the form of an + // initial construct) or implicitly (attached to the variable declarations). + bool hasInitialStatesExpression; + + // The expression contained in the initial construct (if any). + storm::expressions::Expression initialStatesExpression; + + // The labels that are defined for this model. + std::vector<Label> labels; + + // A mapping from label names to their corresponding indices. + std::map<std::string, uint_fast64_t> labelToIndexMap; + + // The set of actions present in this program. + std::set<std::string> actions; + + // A map of actions to the set of modules containing commands labelled with this action. + std::map<std::string, std::set<uint_fast64_t>> actionsToModuleIndexMap; + + // A mapping from variable names to the modules in which they were declared. + std::map<std::string, uint_fast64_t> variableToModuleIndexMap; + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_PROGRAM_H_ */ diff --git a/src/storage/prism/RewardModel.cpp b/src/storage/prism/RewardModel.cpp new file mode 100644 index 000000000..a6c68b34f --- /dev/null +++ b/src/storage/prism/RewardModel.cpp @@ -0,0 +1,57 @@ +#include "src/storage/prism/RewardModel.h" + +namespace storm { + namespace prism { + RewardModel::RewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), rewardModelName(rewardModelName), stateRewards(stateRewards), transitionRewards(transitionRewards) { + // Nothing to do here. + } + + std::string const& RewardModel::getName() const { + return this->rewardModelName; + } + + bool RewardModel::hasStateRewards() const { + return this->stateRewards.size() > 0; + } + + std::vector<storm::prism::StateReward> const& RewardModel::getStateRewards() const { + return this->stateRewards; + } + + bool RewardModel::hasTransitionRewards() const { + return this->transitionRewards.size() > 0; + } + + std::vector<storm::prism::TransitionReward> const& RewardModel::getTransitionRewards() const { + return this->transitionRewards; + } + + RewardModel RewardModel::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + std::vector<StateReward> newStateRewards; + newStateRewards.reserve(this->getStateRewards().size()); + for (auto const& stateReward : this->getStateRewards()) { + newStateRewards.emplace_back(stateReward.substitute(substitution)); + } + + std::vector<TransitionReward> newTransitionRewards; + newTransitionRewards.reserve(this->getTransitionRewards().size()); + for (auto const& transitionReward : this->getTransitionRewards()) { + newTransitionRewards.emplace_back(transitionReward.substitute(substitution)); + } + return RewardModel(this->getName(), newStateRewards, newTransitionRewards, this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel) { + stream << "rewards \"" << rewardModel.getName() << "\"" << std::endl; + for (auto const& reward : rewardModel.getStateRewards()) { + stream << reward << std::endl; + } + for (auto const& reward : rewardModel.getTransitionRewards()) { + stream << reward << std::endl; + } + stream << "endrewards" << std::endl; + return stream; + } + + } // namespace prism +} // namespace storm diff --git a/src/storage/prism/RewardModel.h b/src/storage/prism/RewardModel.h new file mode 100644 index 000000000..3bb68d1b5 --- /dev/null +++ b/src/storage/prism/RewardModel.h @@ -0,0 +1,95 @@ +#ifndef STORM_STORAGE_PRISM_REWARDMODEL_H_ +#define STORM_STORAGE_PRISM_REWARDMODEL_H_ + +#include <string> +#include <vector> +#include <map> + +#include "src/storage/prism/StateReward.h" +#include "src/storage/prism/TransitionReward.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class RewardModel : public LocatedInformation { + public: + /*! + * Creates a reward model with the given name, state and transition rewards. + * + * @param rewardModelName The name of the reward model. + * @param stateRewards A vector of state-based rewards. + * @param transitionRewards A vector of transition-based rewards. + * @param filename The filename in which the reward model is defined. + * @param lineNumber The line number in which the reward model is defined. + */ + RewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + RewardModel() = default; + RewardModel(RewardModel const& other) = default; + RewardModel& operator=(RewardModel const& other)= default; +#ifndef WINDOWS + RewardModel(RewardModel&& other) = default; + RewardModel& operator=(RewardModel&& other) = default; +#endif + + /*! + * Retrieves the name of the reward model. + * + * @return The name of the reward model. + */ + std::string const& getName() const; + + /*! + * Retrieves whether there are any state rewards. + * + * @return True iff there are any state rewards. + */ + bool hasStateRewards() const; + + /*! + * Retrieves all state rewards associated with this reward model. + * + * @return The state rewards associated with this reward model. + */ + std::vector<storm::prism::StateReward> const& getStateRewards() const; + + /*! + * Retrieves whether there are any transition rewards. + * + * @return True iff there are any transition rewards. + */ + bool hasTransitionRewards() const; + + /*! + * Retrieves all transition rewards associated with this reward model. + * + * @return The transition rewards associated with this reward model. + */ + std::vector<storm::prism::TransitionReward> const& getTransitionRewards() const; + + /*! + * Substitutes all identifiers in the reward model according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting reward model. + */ + RewardModel substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel); + + private: + // The name of the reward model. + std::string rewardModelName; + + // The state-based rewards associated with this reward model. + std::vector<storm::prism::StateReward> stateRewards; + + // The transition-based rewards associated with this reward model. + std::vector<storm::prism::TransitionReward> transitionRewards; + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_REWARDMODEL_H_ */ diff --git a/src/storage/prism/StateReward.cpp b/src/storage/prism/StateReward.cpp new file mode 100644 index 000000000..ab2f0974b --- /dev/null +++ b/src/storage/prism/StateReward.cpp @@ -0,0 +1,26 @@ +#include "src/storage/prism/StateReward.h" + +namespace storm { + namespace prism { + StateReward::StateReward(storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), statePredicateExpression(statePredicateExpression), rewardValueExpression(rewardValueExpression) { + // Nothing to do here. + } + + storm::expressions::Expression const& StateReward::getStatePredicateExpression() const { + return this->statePredicateExpression; + } + + storm::expressions::Expression const& StateReward::getRewardValueExpression() const { + return this->rewardValueExpression; + } + + StateReward StateReward::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return StateReward(this->getStatePredicateExpression().substitute<std::map>(substitution), this->getRewardValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, StateReward const& stateReward) { + stream << "\t" << stateReward.getStatePredicateExpression() << ": " << stateReward.getRewardValueExpression() << ";"; + return stream; + } + } // namespace prism +} // namespace storm diff --git a/src/storage/prism/StateReward.h b/src/storage/prism/StateReward.h new file mode 100644 index 000000000..f64dc9e4d --- /dev/null +++ b/src/storage/prism/StateReward.h @@ -0,0 +1,69 @@ +#ifndef STORM_STORAGE_PRISM_STATEREWARD_H_ +#define STORM_STORAGE_PRISM_STATEREWARD_H_ + +#include <map> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/expressions/Expression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class StateReward : public LocatedInformation { + public: + /*! + * Creates a state reward for the states satisfying the given expression with the value given by a second + * expression. + * + * @param statePredicateExpression The predicate that states earning this state-based reward need to satisfy. + * @param rewardValueExpression An expression specifying the values of the rewards to attach to the states. + * @param filename The filename in which the state reward is defined. + * @param lineNumber The line number in which the state reward is defined. + */ + StateReward(storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + StateReward() = default; + StateReward(StateReward const& other) = default; + StateReward& operator=(StateReward const& other)= default; +#ifndef WINDOWS + StateReward(StateReward&& other) = default; + StateReward& operator=(StateReward&& other) = default; +#endif + + /*! + * Retrieves the state predicate that is associated with this state reward. + * + * @return The state predicate that is associated with this state reward. + */ + storm::expressions::Expression const& getStatePredicateExpression() const; + + /*! + * Retrieves the reward value associated with this state reward. + * + * @return The reward value associated with this state reward. + */ + storm::expressions::Expression const& getRewardValueExpression() const; + + /*! + * Substitutes all identifiers in the state reward according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting state reward. + */ + StateReward substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, StateReward const& stateReward); + + private: + // The predicate that characterizes the states that obtain this reward. + storm::expressions::Expression statePredicateExpression; + + // The expression that specifies the value of the reward obtained. + storm::expressions::Expression rewardValueExpression; + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_STATEREWARD_H_ */ diff --git a/src/storage/prism/TransitionReward.cpp b/src/storage/prism/TransitionReward.cpp new file mode 100644 index 000000000..0034231d8 --- /dev/null +++ b/src/storage/prism/TransitionReward.cpp @@ -0,0 +1,31 @@ +#include "src/storage/prism/TransitionReward.h" + +namespace storm { + namespace prism { + TransitionReward::TransitionReward(std::string const& commandName, storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), commandName(commandName), statePredicateExpression(statePredicateExpression), rewardValueExpression(rewardValueExpression) { + // Nothing to do here. + } + + std::string const& TransitionReward::getActionName() const { + return this->commandName; + } + + storm::expressions::Expression const& TransitionReward::getStatePredicateExpression() const { + return this->statePredicateExpression; + } + + storm::expressions::Expression const& TransitionReward::getRewardValueExpression() const { + return this->rewardValueExpression; + } + + TransitionReward TransitionReward::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + return TransitionReward(this->getActionName(), this->getStatePredicateExpression().substitute<std::map>(substitution), this->getRewardValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, TransitionReward const& transitionReward) { + stream << "\t[" << transitionReward.getActionName() << "] " << transitionReward.getStatePredicateExpression() << ": " << transitionReward.getRewardValueExpression() << ";"; + return stream; + } + + } // namespace prism +} // namespace storm diff --git a/src/storage/prism/TransitionReward.h b/src/storage/prism/TransitionReward.h new file mode 100644 index 000000000..2c118cec7 --- /dev/null +++ b/src/storage/prism/TransitionReward.h @@ -0,0 +1,82 @@ +#ifndef STORM_STORAGE_PRISM_TRANSITIONREWARD_H_ +#define STORM_STORAGE_PRISM_TRANSITIONREWARD_H_ + +#include <map> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/expressions/Expression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class TransitionReward : public LocatedInformation { + public: + /*! + * Creates a transition reward for the transitions with the given name emanating from states satisfying the + * given expression with the value given by another expression. + * + * @param actionName The name of the command that obtains this reward. + * @param statePredicateExpression The predicate that needs to hold before taking a transition with the previously + * specified name in order to obtain the reward. + * @param rewardValueExpression An expression specifying the values of the rewards to attach to the transitions. + * @param filename The filename in which the transition reward is defined. + * @param lineNumber The line number in which the transition reward is defined. + */ + TransitionReward(std::string const& actionName, storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + TransitionReward() = default; + TransitionReward(TransitionReward const& other) = default; + TransitionReward& operator=(TransitionReward const& other)= default; +#ifndef WINDOWS + TransitionReward(TransitionReward&& other) = default; + TransitionReward& operator=(TransitionReward&& other) = default; +#endif + + /*! + * Retrieves the action name that is associated with this transition reward. + * + * @return The action name that is associated with this transition reward. + */ + std::string const& getActionName() const; + + /*! + * Retrieves the state predicate expression that is associated with this state reward. + * + * @return The state predicate expression that is associated with this state reward. + */ + storm::expressions::Expression const& getStatePredicateExpression() const; + + /*! + * Retrieves the reward value expression associated with this state reward. + * + * @return The reward value expression associated with this state reward. + */ + storm::expressions::Expression const& getRewardValueExpression() const; + + /*! + * Substitutes all identifiers in the transition reward according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting transition reward. + */ + TransitionReward substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, TransitionReward const& transitionReward); + + private: + // The name of the command this transition-based reward is attached to. + std::string commandName; + + // A predicate that needs to be satisfied by states for the reward to be obtained (by taking + // a corresponding command transition). + storm::expressions::Expression statePredicateExpression; + + // The expression specifying the value of the reward obtained along the transitions. + storm::expressions::Expression rewardValueExpression; + }; + + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_TRANSITIONREWARD_H_ */ diff --git a/src/storage/prism/Update.cpp b/src/storage/prism/Update.cpp new file mode 100644 index 000000000..2e01187c9 --- /dev/null +++ b/src/storage/prism/Update.cpp @@ -0,0 +1,64 @@ +#include "Update.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/OutOfRangeException.h" + +namespace storm { + namespace prism { + Update::Update(uint_fast64_t globalIndex, storm::expressions::Expression const& likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), likelihoodExpression(likelihoodExpression), assignments(assignments), variableToAssignmentIndexMap(), globalIndex(globalIndex) { + this->createAssignmentMapping(); + } + + storm::expressions::Expression const& Update::getLikelihoodExpression() const { + return likelihoodExpression; + } + + std::size_t Update::getNumberOfAssignments() const { + return this->assignments.size(); + } + + std::vector<storm::prism::Assignment> const& Update::getAssignments() const { + return this->assignments; + } + + storm::prism::Assignment const& Update::getAssignment(std::string const& variableName) const { + auto const& variableIndexPair = this->variableToAssignmentIndexMap.find(variableName); + LOG_THROW(variableIndexPair != this->variableToAssignmentIndexMap.end(), storm::exceptions::OutOfRangeException, "Variable '" << variableName << "' is not assigned in update."); + return this->getAssignments()[variableIndexPair->second]; + } + + uint_fast64_t Update::getGlobalIndex() const { + return this->globalIndex; + } + + void Update::createAssignmentMapping() { + this->variableToAssignmentIndexMap.clear(); + for (uint_fast64_t assignmentIndex = 0; assignmentIndex < this->getAssignments().size(); ++assignmentIndex) { + this->variableToAssignmentIndexMap[this->getAssignments()[assignmentIndex].getVariableName()] = assignmentIndex; + } + } + + Update Update::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const { + std::vector<Assignment> newAssignments; + newAssignments.reserve(this->getNumberOfAssignments()); + for (auto const& assignment : this->getAssignments()) { + newAssignments.emplace_back(assignment.substitute(substitution)); + } + + return Update(this->getGlobalIndex(), this->getLikelihoodExpression().substitute<std::map>(substitution), newAssignments, this->getFilename(), this->getLineNumber()); + } + + std::ostream& operator<<(std::ostream& stream, Update const& update) { + stream << update.getLikelihoodExpression() << " : "; + uint_fast64_t i = 0; + for (auto const& assignment : update.getAssignments()) { + stream << assignment; + if (i < update.getAssignments().size() - 1) { + stream << " & "; + } + ++i; + } + return stream; + } + + } // namespace ir +} // namespace storm diff --git a/src/storage/prism/Update.h b/src/storage/prism/Update.h new file mode 100644 index 000000000..b48aa99e4 --- /dev/null +++ b/src/storage/prism/Update.h @@ -0,0 +1,100 @@ +#ifndef STORM_STORAGE_PRISM_UPDATE_H_ +#define STORM_STORAGE_PRISM_UPDATE_H_ + +#include <vector> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/prism/Assignment.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Update : public LocatedInformation { + public: + /*! + * Creates an update with the given expression specifying the likelihood and assignments. + * + * @param globalIndex The global index of the update. + * @param likelihoodExpression An expression specifying the likelihood of this update. + * @param assignments A assignments to variables. + * @param filename The filename in which the update is defined. + * @param lineNumber The line number in which the update is defined. + */ + Update(uint_fast64_t globalIndex, storm::expressions::Expression const& likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + // Create default implementations of constructors/assignment. + Update() = default; + Update(Update const& other) = default; + Update& operator=(Update const& other)= default; +#ifndef WINDOWS + Update(Update&& other) = default; + Update& operator=(Update&& other) = default; +#endif + + /*! + * Retrieves the expression for the likelihood of this update. + * + * @return The expression for the likelihood of this update. + */ + storm::expressions::Expression const& getLikelihoodExpression() const; + + /*! + * Retrieves the number of assignments associated with this update. + * + * @return The number of assignments associated with this update. + */ + std::size_t getNumberOfAssignments() const; + + /*! + * Retrieves a reference to the map of variable names to their respective assignments. + * + * @return A reference to the map of variable names to their respective assignments. + */ + std::vector<storm::prism::Assignment> const& getAssignments() const; + + /*! + * Retrieves a reference to the assignment for the variable with the given name. + * + * @return A reference to the assignment for the variable with the given name. + */ + storm::prism::Assignment const& getAssignment(std::string const& variableName) const; + + /*! + * Retrieves the global index of the update, that is, a unique index over all modules. + * + * @return The global index of the update. + */ + uint_fast64_t getGlobalIndex() const; + + /*! + * Substitutes all identifiers in the update according to the given map. + * + * @param substitution The substitution to perform. + * @return The resulting update. + */ + Update substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const; + + friend std::ostream& operator<<(std::ostream& stream, Update const& assignment); + + private: + /*! + * Creates the internal mapping of variables to their assignments. + */ + void createAssignmentMapping(); + + // An expression specifying the likelihood of taking this update. + storm::expressions::Expression likelihoodExpression; + + // The assignments of this update. + std::vector<storm::prism::Assignment> assignments; + + // A mapping from variable names to their assignments. + std::map<std::string, uint_fast64_t> variableToAssignmentIndexMap; + + // The global index of the update. + uint_fast64_t globalIndex; + }; + } // namespace prism +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_UPDATE_H_ */ diff --git a/src/storage/prism/Variable.cpp b/src/storage/prism/Variable.cpp new file mode 100644 index 000000000..e6c884813 --- /dev/null +++ b/src/storage/prism/Variable.cpp @@ -0,0 +1,27 @@ +#include <map> + +#include "src/storage/prism/Variable.h" + +namespace storm { + namespace prism { + Variable::Variable(std::string const& name, storm::expressions::Expression const& initialValueExpression, bool defaultInitialValue, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(name), initialValueExpression(initialValueExpression), defaultInitialValue(defaultInitialValue) { + // Nothing to do here. + } + + Variable::Variable(Variable const& oldVariable, std::string const& newName, std::map<std::string, std::string> const& renaming, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(newName), initialValueExpression(oldVariable.getInitialValueExpression().substitute<std::map>(renaming)), defaultInitialValue(oldVariable.hasDefaultInitialValue()) { + // Intentionally left empty. + } + + std::string const& Variable::getName() const { + return this->name; + } + + bool Variable::hasDefaultInitialValue() const { + return this->defaultInitialValue; + } + + storm::expressions::Expression const& Variable::getInitialValueExpression() const { + return this->initialValueExpression; + } + } // namespace prism +} // namespace storm diff --git a/src/storage/prism/Variable.h b/src/storage/prism/Variable.h new file mode 100644 index 000000000..a4cb76cb9 --- /dev/null +++ b/src/storage/prism/Variable.h @@ -0,0 +1,84 @@ +#ifndef STORM_STORAGE_PRISM_VARIABLE_H_ +#define STORM_STORAGE_PRISM_VARIABLE_H_ + +#include <map> + +#include "src/storage/prism/LocatedInformation.h" +#include "src/storage/expressions/Expression.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace prism { + class Variable : public LocatedInformation { + public: + // Create default implementations of constructors/assignment. + Variable(Variable const& otherVariable) = default; + Variable& operator=(Variable const& otherVariable)= default; +#ifndef WINDOWS + Variable(Variable&& otherVariable) = default; + Variable& operator=(Variable&& otherVariable) = default; +#endif + + /*! + * Retrieves the name of the variable. + * + * @return The name of the variable. + */ + std::string const& getName() const; + + /*! + * Retrieves the expression defining the initial value of the variable. + * + * @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. + * + * @return True iff the variable has the default initial value. + */ + bool hasDefaultInitialValue() const; + + // Make the constructors protected to forbid instantiation of this class. + protected: + Variable() = default; + + /*! + * Creates a variable with the given name and initial value. + * + * @param name The name of the variable. + * @param initialValueExpression The constant expression that defines the initial value of the variable. + * @param hasDefaultInitialValue A flag indicating whether the initial value of the variable is its default + * value. + * @param filename The filename in which the variable is defined. + * @param lineNumber The line number in which the variable is defined. + */ + Variable(std::string const& name, storm::expressions::Expression const& initialValueExpression, bool defaultInitialValue, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + /*! + * Creates a copy of the given variable and performs the provided renaming. + * + * @param oldVariable The variable to copy. + * @param newName New name of this variable. + * @param renaming A mapping from names that are to be renamed to the names they are to be replaced with. + * @param filename The filename in which the variable is defined. + * @param lineNumber The line number in which the variable is defined. + */ + Variable(Variable const& oldVariable, std::string const& newName, std::map<std::string, std::string> const& renaming, std::string const& filename = "", uint_fast64_t lineNumber = 0); + + private: + // The name of the variable. + std::string name; + + // 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 +} // namespace storm + +#endif /* STORM_STORAGE_PRISM_VARIABLE_H_ */ diff --git a/src/storm.cpp b/src/storm.cpp index a13bf8e23..c7b40247a 100644 --- a/src/storm.cpp +++ b/src/storm.cpp @@ -34,7 +34,7 @@ #include "src/solver/GmmxxNondeterministicLinearEquationSolver.h" #include "src/solver/GurobiLpSolver.h" #include "src/counterexamples/MILPMinimalLabelSetGenerator.h" -#include "src/counterexamples/SMTMinimalCommandSetGenerator.h" +// #include "src/counterexamples/SMTMinimalCommandSetGenerator.h" #include "src/counterexamples/PathBasedSubsystemGenerator.h" #include "src/parser/AutoParser.h" #include "src/parser/MarkovAutomatonParser.h" @@ -54,10 +54,11 @@ #include "log4cplus/loggingmacros.h" #include "log4cplus/consoleappender.h" #include "log4cplus/fileappender.h" +log4cplus::Logger logger; #include "src/parser/PrismParser.h" #include "src/adapters/ExplicitModelAdapter.h" -#include "src/adapters/SymbolicModelAdapter.h" +// #include "src/adapters/SymbolicModelAdapter.h" #include "src/exceptions/InvalidSettingsException.h" @@ -121,8 +122,6 @@ void printUsage() { #endif } -log4cplus::Logger logger; - /*! * Initializes the logging framework and sets up logging to console. */ @@ -535,7 +534,7 @@ int main(const int argc, const char* argv[]) { // First, we build the model using the given symbolic model description and constant definitions. std::string const& programFile = s->getOptionByLongName("symbolic").getArgument(0).getValueAsString(); std::string const& constants = s->getOptionByLongName("constants").getArgument(0).getValueAsString(); - storm::ir::Program program = storm::parser::PrismParserFromFile(programFile); + storm::prism::Program program = storm::parser::PrismParser::parse(programFile); std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program, constants); model->printModelInformationToStream(std::cout); @@ -559,7 +558,7 @@ int main(const int argc, const char* argv[]) { if (useMILP) { storm::counterexamples::MILPMinimalLabelSetGenerator<double>::computeCounterexample(program, *mdp, formulaPtr); } else { - storm::counterexamples::SMTMinimalCommandSetGenerator<double>::computeCounterexample(program, constants, *mdp, formulaPtr); + // storm::counterexamples::SMTMinimalCommandSetGenerator<double>::computeCounterexample(program, constants, *mdp, formulaPtr); } // Once we are done with the formula, delete it. diff --git a/src/utility/IRUtility.h b/src/utility/IRUtility.h deleted file mode 100644 index a75f1972d..000000000 --- a/src/utility/IRUtility.h +++ /dev/null @@ -1,517 +0,0 @@ -/* - * IRUtility.h - * - * Created on: 05.10.2013 - * Author: Christian Dehnert - */ - -#ifndef STORM_UTILITY_IRUTILITY_H_ -#define STORM_UTILITY_IRUTILITY_H_ - -#include <boost/algorithm/string.hpp> - -#include "src/storage/LabeledValues.h" -#include "src/ir/IR.h" -#include "src/exceptions/InvalidArgumentException.h" - -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" - -extern log4cplus::Logger logger; - -namespace storm { - namespace utility { - namespace ir { - - /*! - * A state of the model, i.e. a valuation of all variables. - */ - typedef std::pair<std::vector<bool>, std::vector<int_fast64_t>> StateType; - - /*! - * A helper class that provides the functionality to compute a hash value for states of the model. - */ - class StateHash { - public: - std::size_t operator()(StateType* state) const { - size_t seed = 0; - for (auto it : state->first) { - boost::hash_combine<bool>(seed, it); - } - for (auto it : state->second) { - boost::hash_combine<int_fast64_t>(seed, it); - } - return seed; - } - }; - - /*! - * A helper class that provides the functionality to compare states of the model wrt. equality. - */ - class StateCompare { - public: - bool operator()(StateType* state1, StateType* state2) const { - return *state1 == *state2; - } - }; - - /*! - * A helper class that provides the functionality to compare states of the model wrt. the relation "<". - */ - class StateLess { - public: - bool operator()(StateType* state1, StateType* state2) const { - // Compare boolean variables. - for (uint_fast64_t i = 0; i < state1->first.size(); ++i) { - if (!state1->first.at(i) && state2->first.at(i)) { - return true; - } - } - // Then compare integer variables. - for (uint_fast64_t i = 0; i < state1->second.size(); ++i) { - if (!state1->second.at(i) && state2->second.at(i)) { - return true; - } - } - return false; - } - }; - - // A structure holding information about a particular choice. - template<typename ValueType, typename KeyType=uint_fast64_t, typename Compare=std::less<uint_fast64_t>> - struct Choice { - public: - Choice(std::string const& actionLabel) : distribution(), actionLabel(actionLabel), choiceLabels() { - // Intentionally left empty. - } - - /*! - * Returns an iterator to the first element of this choice. - * - * @return An iterator to the first element of this choice. - */ - typename std::map<KeyType, ValueType>::iterator begin() { - return distribution.begin(); - } - - /*! - * Returns an iterator to the first element of this choice. - * - * @return An iterator to the first element of this choice. - */ - typename std::map<KeyType, ValueType>::const_iterator begin() const { - return distribution.cbegin(); - } - - /*! - * Returns an iterator that points past the elements of this choice. - * - * @return An iterator that points past the elements of this choice. - */ - typename std::map<KeyType, ValueType>::iterator end() { - return distribution.end(); - } - - /*! - * Returns an iterator that points past the elements of this choice. - * - * @return An iterator that points past the elements of this choice. - */ - typename std::map<KeyType, ValueType>::const_iterator end() const { - return distribution.cend(); - } - - /*! - * Returns an iterator to the element with the given key, if there is one. Otherwise, the iterator points to - * distribution.end(). - * - * @param value The value to find. - * @return An iterator to the element with the given key, if there is one. - */ - typename std::map<KeyType, ValueType>::iterator find(uint_fast64_t value) { - return distribution.find(value); - } - - /*! - * Inserts the contents of this object to the given output stream. - * - * @param out The stream in which to insert the contents. - */ - friend std::ostream& operator<<(std::ostream& out, Choice<ValueType> const& choice) { - out << "<"; - for (auto const& stateProbabilityPair : choice.distribution) { - out << stateProbabilityPair.first << " : " << stateProbabilityPair.second << ", "; - } - out << ">"; - return out; - } - - /*! - * Adds the given label to the labels associated with this choice. - * - * @param label The label to associate with this choice. - */ - void addChoiceLabel(uint_fast64_t label) { - choiceLabels.insert(label); - } - - /*! - * Adds the given label set to the labels associated with this choice. - * - * @param labelSet The label set to associate with this choice. - */ - void addChoiceLabels(boost::container::flat_set<uint_fast64_t> const& labelSet) { - for (uint_fast64_t label : labelSet) { - addChoiceLabel(label); - } - } - - /*! - * Retrieves the set of labels associated with this choice. - * - * @return The set of labels associated with this choice. - */ - boost::container::flat_set<uint_fast64_t> const& getChoiceLabels() const { - return choiceLabels; - } - - /*! - * Retrieves the action label of this choice. - * - * @return The action label of this choice. - */ - std::string const& getActionLabel() const { - return actionLabel; - } - - /*! - * Retrieves the entry in the choice that is associated with the given state and creates one if none exists, - * yet. - * - * @param state The state for which to add the entry. - * @return A reference to the entry that is associated with the given state. - */ - ValueType& getOrAddEntry(uint_fast64_t state) { - auto stateProbabilityPair = distribution.find(state); - - if (stateProbabilityPair == distribution.end()) { - distribution[state] = ValueType(); - } - return distribution.at(state); - } - - /*! - * Retrieves the entry in the choice that is associated with the given state and creates one if none exists, - * yet. - * - * @param state The state for which to add the entry. - * @return A reference to the entry that is associated with the given state. - */ - ValueType const& getOrAddEntry(uint_fast64_t state) const { - auto stateProbabilityPair = distribution.find(state); - - if (stateProbabilityPair == distribution.end()) { - distribution[state] = ValueType(); - } - return distribution.at(state); - } - - private: - // The distribution that is associated with the choice. - std::map<KeyType, ValueType, Compare> distribution; - - // The label of the choice. - std::string actionLabel; - - // The labels that are associated with this choice. - boost::container::flat_set<uint_fast64_t> choiceLabels; - }; - - /*! - * Adds the target state and probability to the given choice and ignores the labels. This function overloads with - * other functions to ensure the proper treatment of labels. - * - * @param choice The choice to which to add the target state and probability. - * @param state The target state of the probability. - * @param probability The probability to reach the target state in one step. - * @param labels A set of labels that is supposed to be associated with this state and probability. NOTE: this - * is ignored by this particular function but not by the overloaded functions. - */ - template<typename ValueType> - void addProbabilityToChoice(Choice<ValueType>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) { - choice.getOrAddEntry(state) += probability; - } - - /*! - * Adds the target state and probability to the given choice and labels it accordingly. This function overloads - * with other functions to ensure the proper treatment of labels. - * - * @param choice The choice to which to add the target state and probability. - * @param state The target state of the probability. - * @param probability The probability to reach the target state in one step. - * @param labels A set of labels that is supposed to be associated with this state and probability. - */ - template<typename ValueType> - void addProbabilityToChoice(Choice<storm::storage::LabeledValues<ValueType>>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) { - auto& labeledEntry = choice.getOrAddEntry(state); - labeledEntry.addValue(probability, labels); - } - - // A structure storing information about the used variables of the program. - struct VariableInformation { - VariableInformation() : booleanVariables(), booleanVariableToIndexMap(), integerVariables(), integerVariableToIndexMap() { - // Intentinally left empty. - } - - // List of all boolean variables. - std::vector<storm::ir::BooleanVariable> booleanVariables; - - // A mapping of boolean variable names to their indices. - std::map<std::string, uint_fast64_t> booleanVariableToIndexMap; - - // List of all integer variables. - std::vector<storm::ir::IntegerVariable> integerVariables; - - // List of all lower bounds for integer variables. - std::vector<int_fast64_t> lowerBounds; - - // List of all upper bounds for integer variables. - std::vector<int_fast64_t> upperBounds; - - // A mapping of integer variable names to their indices. - std::map<std::string, uint_fast64_t> integerVariableToIndexMap; - }; - - /*! - * Aggregates information about the variables in the program. - * - * @param program The program whose variables to aggregate. - * @return A structure containing information about the variables in the program. - */ - static VariableInformation createVariableInformation(storm::ir::Program const& program) { - VariableInformation result; - - uint_fast64_t numberOfIntegerVariables = 0; - uint_fast64_t numberOfBooleanVariables = 0; - - // Count number of variables. - numberOfBooleanVariables += program.getNumberOfGlobalBooleanVariables(); - numberOfIntegerVariables += program.getNumberOfGlobalIntegerVariables(); - for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) { - numberOfBooleanVariables += program.getModule(i).getNumberOfBooleanVariables(); - numberOfIntegerVariables += program.getModule(i).getNumberOfIntegerVariables(); - } - - // Resize the variable vectors appropriately. - result.booleanVariables.resize(numberOfBooleanVariables); - result.integerVariables.resize(numberOfIntegerVariables); - result.lowerBounds.resize(numberOfIntegerVariables); - result.upperBounds.resize(numberOfIntegerVariables); - - // Create variables. - for (uint_fast64_t i = 0; i < program.getNumberOfGlobalBooleanVariables(); ++i) { - storm::ir::BooleanVariable const& var = program.getGlobalBooleanVariable(i); - result.booleanVariables[var.getGlobalIndex()] = var; - result.booleanVariableToIndexMap[var.getName()] = var.getGlobalIndex(); - } - for (uint_fast64_t i = 0; i < program.getNumberOfGlobalIntegerVariables(); ++i) { - storm::ir::IntegerVariable const& var = program.getGlobalIntegerVariable(i); - result.integerVariables[var.getGlobalIndex()] = var; - result.integerVariableToIndexMap[var.getName()] = var.getGlobalIndex(); - result.lowerBounds[var.getGlobalIndex()] = var.getLowerBound()->getValueAsInt(nullptr); - result.upperBounds[var.getGlobalIndex()] = var.getUpperBound()->getValueAsInt(nullptr); - } - for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) { - storm::ir::Module const& module = program.getModule(i); - - for (uint_fast64_t j = 0; j < module.getNumberOfBooleanVariables(); ++j) { - storm::ir::BooleanVariable const& var = module.getBooleanVariable(j); - result.booleanVariables[var.getGlobalIndex()] = var; - result.booleanVariableToIndexMap[var.getName()] = var.getGlobalIndex(); - } - for (uint_fast64_t j = 0; j < module.getNumberOfIntegerVariables(); ++j) { - storm::ir::IntegerVariable const& var = module.getIntegerVariable(j); - result.integerVariables[var.getGlobalIndex()] = var; - result.integerVariableToIndexMap[var.getName()] = var.getGlobalIndex(); - result.lowerBounds[var.getGlobalIndex()] = var.getLowerBound()->getValueAsInt(nullptr); - result.upperBounds[var.getGlobalIndex()] = var.getUpperBound()->getValueAsInt(nullptr); - } - } - - return result; - } - - /*! - * Generates the initial state of the given program. - * - * @param program The program for which to construct the initial state. - * @param variableInformation A structure with information about the variables in the program. - * @return The initial state. - */ - static StateType* getInitialState(storm::ir::Program const& program, VariableInformation const& variableInformation) { - StateType* initialState = new StateType(); - initialState->first.resize(variableInformation.booleanVariables.size()); - initialState->second.resize(variableInformation.integerVariables.size()); - - // Start with boolean variables. - for (uint_fast64_t i = 0; i < variableInformation.booleanVariables.size(); ++i) { - // Check if an initial value is given - if (variableInformation.booleanVariables[i].getInitialValue().get() == nullptr) { - // If no initial value was given, we assume that the variable is initially false. - std::get<0>(*initialState)[i] = false; - } else { - // Initial value was given. - bool initialValue = variableInformation.booleanVariables[i].getInitialValue()->getValueAsBool(nullptr); - std::get<0>(*initialState)[i] = initialValue; - } - } - - // Now process integer variables. - for (uint_fast64_t i = 0; i < variableInformation.integerVariables.size(); ++i) { - // Check if an initial value was given. - if (variableInformation.integerVariables[i].getInitialValue().get() == nullptr) { - // No initial value was given, so we assume that the variable initially has the least value it can take. - std::get<1>(*initialState)[i] = variableInformation.integerVariables[i].getLowerBound()->getValueAsInt(nullptr); - } else { - // Initial value was given. - int_fast64_t initialValue = variableInformation.integerVariables[i].getInitialValue()->getValueAsInt(nullptr); - std::get<1>(*initialState)[i] = initialValue; - } - } - - LOG4CPLUS_DEBUG(logger, "Generated initial state."); - return initialState; - } - - /*! - * Sets some boolean variable in the given state object. - * - * @param state The state to modify. - * @param index The index of the boolean variable to modify. - * @param value The new value of the variable. - */ - static void setValue(StateType* state, uint_fast64_t index, bool value) { - std::get<0>(*state)[index] = value; - } - - /*! - * Set some integer variable in the given state object. - * - * @param state The state to modify. - * @param index index of the integer variable to modify. - * @param value The new value of the variable. - */ - static void setValue(StateType* state, uint_fast64_t index, int_fast64_t value) { - std::get<1>(*state)[index] = value; - } - - /*! - * Defines the undefined constants of the given program using the given string. - * - * @param program The program in which to define the constants. - * @param constantDefinitionString A comma-separated list of constant definitions. - */ - static void defineUndefinedConstants(storm::ir::Program& program, std::string const& constantDefinitionString) { - if (!constantDefinitionString.empty()) { - // Parse the string that defines the undefined constants of the model and make sure that it contains exactly - // one value for each undefined constant of the model. - std::vector<std::string> definitions; - boost::split(definitions, constantDefinitionString, boost::is_any_of(",")); - for (auto& definition : definitions) { - boost::trim(definition); - - // Check whether the token could be a legal constant definition. - uint_fast64_t positionOfAssignmentOperator = definition.find('='); - if (positionOfAssignmentOperator == std::string::npos) { - throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: syntax error."; - } - - // Now extract the variable name and the value from the string. - std::string constantName = definition.substr(0, positionOfAssignmentOperator); - boost::trim(constantName); - std::string value = definition.substr(positionOfAssignmentOperator + 1); - boost::trim(value); - - // Check whether the constant is a legal undefined constant of the program and if so, of what type it is. - if (program.hasUndefinedBooleanConstant(constantName)) { - if (value == "true") { - program.getUndefinedBooleanConstantExpression(constantName)->define(true); - } else if (value == "false") { - program.getUndefinedBooleanConstantExpression(constantName)->define(false); - } else { - throw storm::exceptions::InvalidArgumentException() << "Illegal value for boolean constant: " << value << "."; - } - } else if (program.hasUndefinedIntegerConstant(constantName)) { - try { - int_fast64_t integerValue = std::stoi(value); - program.getUndefinedIntegerConstantExpression(constantName)->define(integerValue); - } catch (std::invalid_argument const&) { - throw storm::exceptions::InvalidArgumentException() << "Illegal value of integer constant: " << value << "."; - } catch (std::out_of_range const&) { - throw storm::exceptions::InvalidArgumentException() << "Illegal value of integer constant: " << value << " (value too big)."; - } - } else if (program.hasUndefinedDoubleConstant(constantName)) { - try { - double doubleValue = std::stod(value); - program.getUndefinedDoubleConstantExpression(constantName)->define(doubleValue); - } catch (std::invalid_argument const&) { - throw storm::exceptions::InvalidArgumentException() << "Illegal value of double constant: " << value << "."; - } catch (std::out_of_range const&) { - throw storm::exceptions::InvalidArgumentException() << "Illegal value of double constant: " << value << " (value too big)."; - } - - } else { - throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: unknown undefined constant " << constantName << "."; - } - } - } - } - - /*! - * Undefines all previously defined constants in the given program. - * - * @param program The program in which to undefine the constants. - */ - static void undefineUndefinedConstants(storm::ir::Program& program) { - for (auto const& nameExpressionPair : program.getBooleanUndefinedConstantExpressionsMap()) { - nameExpressionPair.second->undefine(); - } - for (auto const& nameExpressionPair : program.getIntegerUndefinedConstantExpressionsMap()) { - nameExpressionPair.second->undefine(); - } - for (auto const& nameExpressionPair : program.getDoubleUndefinedConstantExpressionsMap()) { - nameExpressionPair.second->undefine(); - } - } - - /*! - * Computes the weakest precondition of the given boolean expression wrt. the given updates. The weakest - * precondition is the most liberal expression that must hold in order to satisfy the given boolean - * expression after performing the updates. The updates must be disjoint in the sense that they must not - * assign an expression to a variable twice or more. - * - * @param expression The expression for which to build the weakest precondition. - * @param update The update with respect to which to compute the weakest precondition. - */ - std::unique_ptr<storm::ir::expressions::BaseExpression> getWeakestPrecondition(std::unique_ptr<storm::ir::expressions::BaseExpression> const& booleanExpression, std::vector<std::reference_wrapper<storm::ir::Update const>> const& updates) { - std::map<std::string, std::reference_wrapper<storm::ir::expressions::BaseExpression>> variableToExpressionMap; - - // Construct the full substitution we need to perform later. - for (auto const& update : updates) { - for (auto const& variableAssignmentPair : update.get().getBooleanAssignments()) { - variableToExpressionMap.emplace(variableAssignmentPair.first, *variableAssignmentPair.second.getExpression()); - } - for (auto const& variableAssignmentPair : update.get().getIntegerAssignments()) { - variableToExpressionMap.emplace(variableAssignmentPair.first, *variableAssignmentPair.second.getExpression()); - } - } - - // Copy the given expression and apply the substitution. - return storm::ir::expressions::BaseExpression::substitute(booleanExpression->clone(), variableToExpressionMap); - } - - } // namespace ir - } // namespace utility -} // namespace storm - -#endif /* STORM_UTILITY_IRUTILITY_H_ */ diff --git a/src/utility/PrismUtility.h b/src/utility/PrismUtility.h new file mode 100644 index 000000000..9ed15411a --- /dev/null +++ b/src/utility/PrismUtility.h @@ -0,0 +1,195 @@ +#ifndef STORM_UTILITY_PRISMUTILITY +#define STORM_UTILITY_PRISMUTILITY + +#include "src/storage/LabeledValues.h" +#include "src/storage/prism/Program.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidArgumentException.h" + +namespace storm { + namespace utility { + namespace prism { + // A structure holding information about a particular choice. + template<typename ValueType, typename KeyType=uint_fast64_t, typename Compare=std::less<uint_fast64_t>> + struct Choice { + public: + Choice(std::string const& actionLabel) : distribution(), actionLabel(actionLabel), choiceLabels() { + // Intentionally left empty. + } + + /*! + * Returns an iterator to the first element of this choice. + * + * @return An iterator to the first element of this choice. + */ + typename std::map<KeyType, ValueType>::iterator begin() { + return distribution.begin(); + } + + /*! + * Returns an iterator to the first element of this choice. + * + * @return An iterator to the first element of this choice. + */ + typename std::map<KeyType, ValueType>::const_iterator begin() const { + return distribution.cbegin(); + } + + /*! + * Returns an iterator that points past the elements of this choice. + * + * @return An iterator that points past the elements of this choice. + */ + typename std::map<KeyType, ValueType>::iterator end() { + return distribution.end(); + } + + /*! + * Returns an iterator that points past the elements of this choice. + * + * @return An iterator that points past the elements of this choice. + */ + typename std::map<KeyType, ValueType>::const_iterator end() const { + return distribution.cend(); + } + + /*! + * Returns an iterator to the element with the given key, if there is one. Otherwise, the iterator points to + * distribution.end(). + * + * @param value The value to find. + * @return An iterator to the element with the given key, if there is one. + */ + typename std::map<KeyType, ValueType>::iterator find(uint_fast64_t value) { + return distribution.find(value); + } + + /*! + * Inserts the contents of this object to the given output stream. + * + * @param out The stream in which to insert the contents. + */ + friend std::ostream& operator<<(std::ostream& out, Choice<ValueType> const& choice) { + out << "<"; + for (auto const& stateProbabilityPair : choice.distribution) { + out << stateProbabilityPair.first << " : " << stateProbabilityPair.second << ", "; + } + out << ">"; + return out; + } + + /*! + * Adds the given label to the labels associated with this choice. + * + * @param label The label to associate with this choice. + */ + void addChoiceLabel(uint_fast64_t label) { + choiceLabels.insert(label); + } + + /*! + * Adds the given label set to the labels associated with this choice. + * + * @param labelSet The label set to associate with this choice. + */ + void addChoiceLabels(boost::container::flat_set<uint_fast64_t> const& labelSet) { + for (uint_fast64_t label : labelSet) { + addChoiceLabel(label); + } + } + + /*! + * Retrieves the set of labels associated with this choice. + * + * @return The set of labels associated with this choice. + */ + boost::container::flat_set<uint_fast64_t> const& getChoiceLabels() const { + return choiceLabels; + } + + /*! + * Retrieves the action label of this choice. + * + * @return The action label of this choice. + */ + std::string const& getActionLabel() const { + return actionLabel; + } + + /*! + * Retrieves the entry in the choice that is associated with the given state and creates one if none exists, + * yet. + * + * @param state The state for which to add the entry. + * @return A reference to the entry that is associated with the given state. + */ + ValueType& getOrAddEntry(uint_fast64_t state) { + auto stateProbabilityPair = distribution.find(state); + + if (stateProbabilityPair == distribution.end()) { + distribution[state] = ValueType(); + } + return distribution.at(state); + } + + /*! + * Retrieves the entry in the choice that is associated with the given state and creates one if none exists, + * yet. + * + * @param state The state for which to add the entry. + * @return A reference to the entry that is associated with the given state. + */ + ValueType const& getOrAddEntry(uint_fast64_t state) const { + auto stateProbabilityPair = distribution.find(state); + + if (stateProbabilityPair == distribution.end()) { + distribution[state] = ValueType(); + } + return distribution.at(state); + } + + private: + // The distribution that is associated with the choice. + std::map<KeyType, ValueType, Compare> distribution; + + // The label of the choice. + std::string actionLabel; + + // The labels that are associated with this choice. + boost::container::flat_set<uint_fast64_t> choiceLabels; + }; + + /*! + * Adds the target state and probability to the given choice and ignores the labels. This function overloads with + * other functions to ensure the proper treatment of labels. + * + * @param choice The choice to which to add the target state and probability. + * @param state The target state of the probability. + * @param probability The probability to reach the target state in one step. + * @param labels A set of labels that is supposed to be associated with this state and probability. NOTE: this + * is ignored by this particular function but not by the overloaded functions. + */ + template<typename ValueType> + void addProbabilityToChoice(Choice<ValueType>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) { + choice.getOrAddEntry(state) += probability; + } + + /*! + * Adds the target state and probability to the given choice and labels it accordingly. This function overloads + * with other functions to ensure the proper treatment of labels. + * + * @param choice The choice to which to add the target state and probability. + * @param state The target state of the probability. + * @param probability The probability to reach the target state in one step. + * @param labels A set of labels that is supposed to be associated with this state and probability. + */ + template<typename ValueType> + void addProbabilityToChoice(Choice<storm::storage::LabeledValues<ValueType>>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) { + auto& labeledEntry = choice.getOrAddEntry(state); + labeledEntry.addValue(probability, labels); + } + } // namespace prism + } // namespace utility +} // namespace storm + +#endif /* STORM_UTILITY_PRISMUTILITY_H_ */ diff --git a/test/functional/parser/ParsePrismTest.cpp b/test/functional/parser/ParsePrismTest.cpp deleted file mode 100644 index 0a8abb420..000000000 --- a/test/functional/parser/ParsePrismTest.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "gtest/gtest.h" -#include "storm-config.h" -#include "src/parser/PrismParser.h" -//#include "src/utility/IoUtility.h" -#include "src/ir/Program.h" -#include "src/adapters/ExplicitModelAdapter.h" -#include "src/models/Dtmc.h" -#include "src/models/Mdp.h" -#include "src/settings/Settings.h" -#include "src/settings/InternalOptionMemento.h" - -TEST(ParsePrismTest, parseCrowds5_5) { - storm::settings::InternalOptionMemento deadlockOption("fixDeadlocks", true); - ASSERT_TRUE(storm::settings::Settings::getInstance()->isSet("fixDeadlocks")); - storm::ir::Program program; - ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.pm")); - std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program); - - ASSERT_EQ(model->getNumberOfStates(), 8607ull); - ASSERT_EQ(model->getNumberOfTransitions(), 15113ull); -} - -TEST(ParsePrismTest, parseTwoDice) { - storm::ir::Program program; - ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.nm")); - - std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program, "", "coinflips"); - - ASSERT_EQ(model->getNumberOfStates(), 169ull); - ASSERT_EQ(model->as<storm::models::AbstractNondeterministicModel<double>>()->getNumberOfChoices(), 254ull); - ASSERT_EQ(model->getNumberOfTransitions(), 436ull); -} diff --git a/test/functional/parser/PrismParserTest.cpp b/test/functional/parser/PrismParserTest.cpp new file mode 100644 index 000000000..739d9ca5b --- /dev/null +++ b/test/functional/parser/PrismParserTest.cpp @@ -0,0 +1,170 @@ +#include "gtest/gtest.h" +#include "storm-config.h" +#include "src/parser/PrismParser.h" + +TEST(PrismParser, SimpleParsingOnlyTest) { + std::string testInput = + R"(dtmc + module mod1 + b : bool; + [a] true -> 1: (b'=true); + endmodule)"; + + storm::prism::Program result; + EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false)); + EXPECT_EQ(1, result.getNumberOfModules()); + EXPECT_EQ(storm::prism::Program::ModelType::DTMC, result.getModelType()); +} + +TEST(PrismParser, StandardModelParsingTest) { + storm::prism::Program result; + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/crowds5_5.pm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/csma2_2.nm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/die.pm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/firewire.nm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3.nm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3_5.pm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/two_dice.nm", false)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/wlan0_collide.nm", false)); +} + +TEST(PrismParser, StandardModelFullTest) { + storm::prism::Program result; + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/crowds5_5.pm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/csma2_2.nm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/die.pm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/firewire.nm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3.nm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3_5.pm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/two_dice.nm", true)); + EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/wlan0_collide.nm", true)); +} + +TEST(PrismParser, SimpleFullTest) { + std::string testInput = + R"(dtmc + module mod1 + b : bool; + [a] true -> 1: (b'=true); + endmodule)"; + + storm::prism::Program result; + EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", true)); + EXPECT_EQ(1, result.getNumberOfModules()); + EXPECT_EQ(storm::prism::Program::ModelType::DTMC, result.getModelType()); +} + +TEST(PrismParser, ComplexFullTest) { + std::string testInput = + R"(ma + + const int a; + const int b = 10; + const bool c; + const bool d = true | false; + const double e; + const double f = 9; + + formula test = a >= 10 & (max(a,b) > floor(e)); + formula test2 = a+b; + formula test3 = (a + b > 10 ? floor(a) : h) + a; + + global g : bool init false; + global h : [0 .. b]; + + module mod1 + i : bool; + j : bool init c; + k : [125..a] init a; + + [a] test&false -> (i'=true)&(k'=1+1) + 1 : (k'=floor(a) <= max(k, b) - 1 + k); + endmodule + + module mod2 + [b] (k > 3) & false & (min(a, 0) < max(h, k)) -> 1-e: (j'=(1-a) * 2 + floor(f)); + endmodule + + module mod3 = mod1 [ i = i1, j = j1, k = k1 ] endmodule + + label "mal" = max(a, 10) > 0; + + init + true + endinit + + rewards "testrewards" + [stateRew] true : a + 7; + max(f, a) <= 8 : 2*b; + endrewards + + rewards "testrewards2" + [stateRew] true : a + 7; + max(f, a) <= 8 : 2*b; + endrewards)"; + + storm::prism::Program result; + result = storm::parser::PrismParser::parseFromString(testInput, "testfile", true); + EXPECT_EQ(storm::prism::Program::ModelType::MA, result.getModelType()); + EXPECT_EQ(3, result.getNumberOfModules()); + EXPECT_EQ(2, result.getNumberOfRewardModels()); + EXPECT_EQ(1, result.getNumberOfLabels()); + EXPECT_TRUE(result.definesInitialStatesExpression()); +} + +TEST(PrismParser, ComplexParsingTest) { + std::string testInput = + R"(ma + + const int a; + const int b = 10; + const bool c; + const bool d = true | false; + const double e; + const double f = 9; + + formula test = (a >= 10 & (max(a, b) > floor(e))); + + global g : bool init false; + global h : [0 .. b]; + + module mod1 + i : bool; + j : bool init c; + k : [125..a] init a; + [a] true -> (i'=true)&(h'=1+1) + 1 : (j'=floor(a) <= max(k, b) - 1 + k); + endmodule + + module mod2 + [b] (x > 3) & false & (min(a, b0) < max(as8, b)) -> y: (x'=(1-g) * 2 + a); + [] s=1 -> (a'=a); + [read] c<N-1 -> 1 : (c'=floor(c) + 1); + endmodule + + module mod3 = mod2 [ x = y ] endmodule + + label "mal" = max(x, i) > 0; + + init + true + endinit + + rewards "testrewards" + [stateRew] true : a + 7; + max(z, f) <= 8 : 2*b; + endrewards + + rewards "testrewards2" + [stateRew] true : a + 7; + max(z, f) <= 8 : 2*b; + endrewards)"; + + storm::prism::Program result; + result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false); + EXPECT_EQ(storm::prism::Program::ModelType::MA, result.getModelType()); + EXPECT_EQ(3, result.getNumberOfModules()); + EXPECT_EQ(2, result.getNumberOfRewardModels()); + EXPECT_EQ(1, result.getNumberOfLabels()); + EXPECT_TRUE(result.definesInitialStatesExpression()); +} \ No newline at end of file diff --git a/test/functional/storage/CuddDdTest.cpp b/test/functional/storage/CuddDdTest.cpp index a92dbc929..8a5be849a 100644 --- a/test/functional/storage/CuddDdTest.cpp +++ b/test/functional/storage/CuddDdTest.cpp @@ -6,9 +6,8 @@ #include "src/storage/dd/DdMetaVariable.h" TEST(CuddDdManager, Constants) { - std::shared_ptr<storm::dd::DdManager<storm::dd::CUDD>> manager(new storm::dd::DdManager<storm::dd::CUDD>()); - - storm::dd::Dd<storm::dd::CUDD> zero; + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + storm::dd::Dd<storm::dd::DdType::CUDD> zero; ASSERT_NO_THROW(zero = manager->getZero()); EXPECT_EQ(0, zero.getNonZeroCount()); @@ -17,7 +16,7 @@ TEST(CuddDdManager, Constants) { EXPECT_EQ(0, zero.getMin()); EXPECT_EQ(0, zero.getMax()); - storm::dd::Dd<storm::dd::CUDD> one; + storm::dd::Dd<storm::dd::DdType::CUDD> one; ASSERT_NO_THROW(one = manager->getOne()); EXPECT_EQ(1, one.getNonZeroCount()); @@ -26,7 +25,7 @@ TEST(CuddDdManager, Constants) { EXPECT_EQ(1, one.getMin()); EXPECT_EQ(1, one.getMax()); - storm::dd::Dd<storm::dd::CUDD> two; + storm::dd::Dd<storm::dd::DdType::CUDD> two; ASSERT_NO_THROW(two = manager->getConstant(2)); EXPECT_EQ(1, two.getNonZeroCount()); @@ -36,9 +35,8 @@ TEST(CuddDdManager, Constants) { EXPECT_EQ(2, two.getMax()); } -TEST(CuddDdManager, MetaVariableTest) { - std::shared_ptr<storm::dd::DdManager<storm::dd::CUDD>> manager(new storm::dd::DdManager<storm::dd::CUDD>()); - +TEST(CuddDdManager, AddGetMetaVariableTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9)); EXPECT_EQ(1, manager->getNumberOfMetaVariables()); @@ -58,9 +56,55 @@ TEST(CuddDdManager, MetaVariableTest) { std::set<std::string> metaVariableSet = {"x", "y", "y'"}; EXPECT_EQ(metaVariableSet, manager->getAllMetaVariableNames()); - ASSERT_THROW(storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x'"), storm::exceptions::InvalidArgumentException); - ASSERT_NO_THROW(storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x")); - storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x"); + ASSERT_THROW(storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x'"), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x")); +} + +TEST(CuddDdManager, EncodingTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + manager->addMetaVariable("x", 1, 9); + + storm::dd::Dd<storm::dd::DdType::CUDD> encoding; + ASSERT_THROW(encoding = manager->getEncoding("x", 0), storm::exceptions::InvalidArgumentException); + ASSERT_THROW(encoding = manager->getEncoding("x", 10), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(encoding = manager->getEncoding("x", 4)); + EXPECT_EQ(1, encoding.getNonZeroCount()); + EXPECT_EQ(6, encoding.getNodeCount()); + EXPECT_EQ(2, encoding.getLeafCount()); +} + +TEST(CuddDdManager, RangeTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9)); + + storm::dd::Dd<storm::dd::DdType::CUDD> range; + ASSERT_THROW(range = manager->getRange("y"), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(range = manager->getRange("x")); + + EXPECT_EQ(9, range.getNonZeroCount()); + EXPECT_EQ(2, range.getLeafCount()); + EXPECT_EQ(6, range.getNodeCount()); +} + +TEST(CuddDdManager, IdentityTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + manager->addMetaVariable("x", 1, 9); + + storm::dd::Dd<storm::dd::DdType::CUDD> range; + ASSERT_THROW(range = manager->getIdentity("y"), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(range = manager->getIdentity("x")); + + EXPECT_EQ(9, range.getNonZeroCount()); + EXPECT_EQ(10, range.getLeafCount()); + EXPECT_EQ(21, range.getNodeCount()); +} + +TEST(CuddDdMetaVariable, AccessorTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + manager->addMetaVariable("x", 1, 9); + EXPECT_EQ(1, manager->getNumberOfMetaVariables()); + ASSERT_NO_THROW(storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x")); + storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x"); EXPECT_EQ(1, metaVariableX.getLow()); EXPECT_EQ(9, metaVariableX.getHigh()); @@ -69,3 +113,153 @@ TEST(CuddDdManager, MetaVariableTest) { EXPECT_EQ(4, metaVariableX.getNumberOfDdVariables()); } +TEST(CuddDd, OperatorTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + manager->addMetaVariable("x", 1, 9); + EXPECT_TRUE(manager->getZero() == manager->getZero()); + EXPECT_FALSE(manager->getZero() == manager->getOne()); + + EXPECT_FALSE(manager->getZero() != manager->getZero()); + EXPECT_TRUE(manager->getZero() != manager->getOne()); + + storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne(); + storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getOne(); + storm::dd::Dd<storm::dd::DdType::CUDD> dd3 = dd1 + dd2; + EXPECT_TRUE(dd3 == manager->getConstant(2)); + + dd3 += manager->getZero(); + EXPECT_TRUE(dd3 == manager->getConstant(2)); + + dd3 = dd1 * manager->getConstant(3); + EXPECT_TRUE(dd3 == manager->getConstant(3)); + + dd3 *= manager->getConstant(2); + EXPECT_TRUE(dd3 == manager->getConstant(6)); + + dd3 = dd1 - dd2; + EXPECT_TRUE(dd3 == manager->getZero()); + + dd3 -= manager->getConstant(-2); + EXPECT_TRUE(dd3 == manager->getConstant(2)); + + dd3 /= manager->getConstant(2); + EXPECT_TRUE(dd3 == manager->getOne()); + + dd3.complement(); + EXPECT_TRUE(dd3 == manager->getZero()); + + dd1 = ~dd3; + EXPECT_TRUE(dd1 == manager->getOne()); + + dd1 = manager->getIdentity("x"); + dd2 = manager->getConstant(5); + + dd3 = dd1.equals(dd2); + EXPECT_EQ(1, dd3.getNonZeroCount()); + + storm::dd::Dd<storm::dd::DdType::CUDD> dd4 = dd1.notEquals(dd2); + EXPECT_TRUE(dd4 == ~dd3); + + dd3 = dd1.less(dd2); + EXPECT_EQ(11, dd3.getNonZeroCount()); + + dd3 = dd1.lessOrEqual(dd2); + EXPECT_EQ(12, dd3.getNonZeroCount()); + + dd3 = dd1.greater(dd2); + EXPECT_EQ(4, dd3.getNonZeroCount()); + + dd3 = dd1.greaterOrEqual(dd2); + EXPECT_EQ(5, dd3.getNonZeroCount()); +} + +TEST(CuddDd, AbstractionTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + manager->addMetaVariablesInterleaved({"x", "x'"}, 1, 9); + storm::dd::Dd<storm::dd::DdType::CUDD> dd1; + storm::dd::Dd<storm::dd::DdType::CUDD> dd2; + storm::dd::Dd<storm::dd::DdType::CUDD> dd3; + + dd1 = manager->getIdentity("x"); + dd2 = manager->getConstant(5); + dd3 = dd1.equals(dd2); + EXPECT_EQ(1, dd3.getNonZeroCount()); + ASSERT_THROW(dd3.existsAbstract({"x'"}), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(dd3.existsAbstract({"x"})); + EXPECT_EQ(1, dd3.getNonZeroCount()); + EXPECT_EQ(1, dd3.getMax()); + + dd3 = dd1.equals(dd2); + dd3 *= manager->getConstant(3); + EXPECT_EQ(1, dd3.getNonZeroCount()); + ASSERT_THROW(dd3.existsAbstract({"x'"}), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(dd3.existsAbstract({"x"})); + EXPECT_TRUE(dd3 == manager->getZero()); + + dd3 = dd1.equals(dd2); + dd3 *= manager->getConstant(3); + ASSERT_THROW(dd3.sumAbstract({"x'"}), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(dd3.sumAbstract({"x"})); + EXPECT_EQ(1, dd3.getNonZeroCount()); + EXPECT_EQ(3, dd3.getMax()); + + dd3 = dd1.equals(dd2); + dd3 *= manager->getConstant(3); + ASSERT_THROW(dd3.minAbstract({"x'"}), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(dd3.minAbstract({"x"})); + EXPECT_EQ(0, dd3.getNonZeroCount()); + EXPECT_EQ(0, dd3.getMax()); + + dd3 = dd1.equals(dd2); + dd3 *= manager->getConstant(3); + ASSERT_THROW(dd3.maxAbstract({"x'"}), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(dd3.maxAbstract({"x"})); + EXPECT_EQ(1, dd3.getNonZeroCount()); + EXPECT_EQ(3, dd3.getMax()); +} + +TEST(CuddDd, SwapTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + + manager->addMetaVariablesInterleaved({"x", "x'"}, 1, 9); + manager->addMetaVariable("z", 2, 8); + storm::dd::Dd<storm::dd::DdType::CUDD> dd1; + storm::dd::Dd<storm::dd::DdType::CUDD> dd2; + + dd1 = manager->getIdentity("x"); + ASSERT_THROW(dd1.swapVariables({std::make_pair("x", "z")}), storm::exceptions::InvalidArgumentException); + ASSERT_NO_THROW(dd1.swapVariables({std::make_pair("x", "x'")})); + EXPECT_TRUE(dd1 == manager->getIdentity("x'")); +} + +TEST(CuddDd, MultiplyMatrixTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + manager->addMetaVariablesInterleaved({"x", "x'"}, 1, 9); + + storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getIdentity("x").equals(manager->getIdentity("x'")); + storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getRange("x'"); + storm::dd::Dd<storm::dd::DdType::CUDD> dd3; + dd1 *= manager->getConstant(2); + + ASSERT_NO_THROW(dd3 = dd1.multiplyMatrix(dd2, {"x'"})); + ASSERT_NO_THROW(dd3.swapVariables({std::make_pair("x", "x'")})); + EXPECT_TRUE(dd3 == dd2 * manager->getConstant(2)); +} + +TEST(CuddDd, GetSetValueTest) { + std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); + manager->addMetaVariable("x", 1, 9); + + storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne(); + ASSERT_NO_THROW(dd1.setValue("x", 4, 2)); + EXPECT_EQ(2, dd1.getLeafCount()); + dd1.exportToDot("dd1.dot"); + + std::map<std::string, int_fast64_t> metaVariableToValueMap; + metaVariableToValueMap.emplace("x", 1); + EXPECT_EQ(1, dd1.getValue(metaVariableToValueMap)); + + metaVariableToValueMap.clear(); + metaVariableToValueMap.emplace("x", 4); + EXPECT_EQ(2, dd1.getValue(metaVariableToValueMap)); +} diff --git a/test/functional/storage/ExpressionTest.cpp b/test/functional/storage/ExpressionTest.cpp new file mode 100644 index 000000000..0c19c5bfb --- /dev/null +++ b/test/functional/storage/ExpressionTest.cpp @@ -0,0 +1,383 @@ +#include <map> + +#include "gtest/gtest.h" +#include "src/storage/expressions/Expression.h" +#include "src/storage/expressions/SimpleValuation.h" +#include "src/exceptions/InvalidTypeException.h" + +TEST(Expression, FactoryMethodTest) { + EXPECT_NO_THROW(storm::expressions::Expression::createBooleanLiteral(true)); + EXPECT_NO_THROW(storm::expressions::Expression::createTrue()); + EXPECT_NO_THROW(storm::expressions::Expression::createFalse()); + EXPECT_NO_THROW(storm::expressions::Expression::createIntegerLiteral(3)); + EXPECT_NO_THROW(storm::expressions::Expression::createDoubleLiteral(3.14)); + EXPECT_NO_THROW(storm::expressions::Expression::createBooleanVariable("x")); + EXPECT_NO_THROW(storm::expressions::Expression::createIntegerVariable("y")); + EXPECT_NO_THROW(storm::expressions::Expression::createDoubleVariable("z")); + EXPECT_NO_THROW(storm::expressions::Expression::createBooleanConstant("a")); + EXPECT_NO_THROW(storm::expressions::Expression::createIntegerConstant("b")); + EXPECT_NO_THROW(storm::expressions::Expression::createDoubleConstant("c")); +} + +TEST(Expression, AccessorTest) { + storm::expressions::Expression trueExpression; + storm::expressions::Expression falseExpression; + storm::expressions::Expression threeExpression; + storm::expressions::Expression piExpression; + storm::expressions::Expression boolVarExpression; + storm::expressions::Expression intVarExpression; + storm::expressions::Expression doubleVarExpression; + storm::expressions::Expression boolConstExpression; + storm::expressions::Expression intConstExpression; + storm::expressions::Expression doubleConstExpression; + + ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue()); + ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse()); + ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3)); + ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14)); + ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x")); + ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y")); + ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z")); + ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a")); + ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b")); + ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c")); + + EXPECT_TRUE(trueExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + EXPECT_TRUE(trueExpression.isConstant()); + EXPECT_TRUE(trueExpression.isTrue()); + EXPECT_FALSE(trueExpression.isFalse()); + EXPECT_TRUE(trueExpression.getVariables() == std::set<std::string>()); + EXPECT_TRUE(trueExpression.getConstants() == std::set<std::string>()); + + EXPECT_TRUE(falseExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + EXPECT_TRUE(falseExpression.isConstant()); + EXPECT_FALSE(falseExpression.isTrue()); + EXPECT_TRUE(falseExpression.isFalse()); + EXPECT_TRUE(falseExpression.getVariables() == std::set<std::string>()); + EXPECT_TRUE(falseExpression.getConstants() == std::set<std::string>()); + + EXPECT_TRUE(threeExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + EXPECT_TRUE(threeExpression.isConstant()); + EXPECT_FALSE(threeExpression.isTrue()); + EXPECT_FALSE(threeExpression.isFalse()); + EXPECT_TRUE(threeExpression.getVariables() == std::set<std::string>()); + EXPECT_TRUE(threeExpression.getConstants() == std::set<std::string>()); + + EXPECT_TRUE(piExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + EXPECT_TRUE(piExpression.isConstant()); + EXPECT_FALSE(piExpression.isTrue()); + EXPECT_FALSE(piExpression.isFalse()); + EXPECT_TRUE(piExpression.getVariables() == std::set<std::string>()); + EXPECT_TRUE(piExpression.getConstants() == std::set<std::string>()); + + EXPECT_TRUE(boolVarExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + EXPECT_FALSE(boolVarExpression.isConstant()); + EXPECT_FALSE(boolVarExpression.isTrue()); + EXPECT_FALSE(boolVarExpression.isFalse()); + EXPECT_TRUE(boolVarExpression.getVariables() == std::set<std::string>({"x"})); + EXPECT_TRUE(boolVarExpression.getConstants() == std::set<std::string>()); + + EXPECT_TRUE(intVarExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + EXPECT_FALSE(intVarExpression.isConstant()); + EXPECT_FALSE(intVarExpression.isTrue()); + EXPECT_FALSE(intVarExpression.isFalse()); + EXPECT_TRUE(intVarExpression.getVariables() == std::set<std::string>({"y"})); + EXPECT_TRUE(intVarExpression.getConstants() == std::set<std::string>()); + + EXPECT_TRUE(doubleVarExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + EXPECT_FALSE(doubleVarExpression.isConstant()); + EXPECT_FALSE(doubleVarExpression.isTrue()); + EXPECT_FALSE(doubleVarExpression.isFalse()); + EXPECT_TRUE(doubleVarExpression.getVariables() == std::set<std::string>({"z"})); + EXPECT_TRUE(doubleVarExpression.getConstants() == std::set<std::string>()); + + EXPECT_TRUE(boolConstExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + EXPECT_FALSE(boolConstExpression.isConstant()); + EXPECT_FALSE(boolConstExpression.isTrue()); + EXPECT_FALSE(boolConstExpression.isFalse()); + EXPECT_TRUE(boolConstExpression.getVariables() == std::set<std::string>()); + EXPECT_TRUE(boolConstExpression.getConstants() == std::set<std::string>({"a"})); + + EXPECT_TRUE(intConstExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + EXPECT_FALSE(intConstExpression.isConstant()); + EXPECT_FALSE(intConstExpression.isTrue()); + EXPECT_FALSE(intConstExpression.isFalse()); + EXPECT_TRUE(intConstExpression.getVariables() == std::set<std::string>()); + EXPECT_TRUE(intConstExpression.getConstants() == std::set<std::string>({"b"})); + + EXPECT_TRUE(doubleConstExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + EXPECT_FALSE(doubleConstExpression.isConstant()); + EXPECT_FALSE(doubleConstExpression.isTrue()); + EXPECT_FALSE(doubleConstExpression.isFalse()); + EXPECT_TRUE(doubleConstExpression.getVariables() == std::set<std::string>()); + EXPECT_TRUE(doubleConstExpression.getConstants() == std::set<std::string>({"c"})); +} + +TEST(Expression, OperatorTest) { + storm::expressions::Expression trueExpression; + storm::expressions::Expression falseExpression; + storm::expressions::Expression threeExpression; + storm::expressions::Expression piExpression; + storm::expressions::Expression boolVarExpression; + storm::expressions::Expression intVarExpression; + storm::expressions::Expression doubleVarExpression; + storm::expressions::Expression boolConstExpression; + storm::expressions::Expression intConstExpression; + storm::expressions::Expression doubleConstExpression; + + ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue()); + ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse()); + ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3)); + ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14)); + ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x")); + ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y")); + ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z")); + ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a")); + ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b")); + ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c")); + + storm::expressions::Expression tempExpression; + + ASSERT_THROW(tempExpression = trueExpression.ite(falseExpression, piExpression), storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = boolConstExpression.ite(threeExpression, doubleVarExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + ASSERT_NO_THROW(tempExpression = boolConstExpression.ite(threeExpression, intVarExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = boolConstExpression.ite(trueExpression, falseExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression + piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression + threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = threeExpression + piExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + ASSERT_NO_THROW(tempExpression = doubleVarExpression + doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + + ASSERT_THROW(tempExpression = trueExpression - piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression - threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = threeExpression - piExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + ASSERT_NO_THROW(tempExpression = doubleVarExpression - doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + + ASSERT_THROW(tempExpression = -trueExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = -threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = -piExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + ASSERT_NO_THROW(tempExpression = -doubleVarExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + + ASSERT_THROW(tempExpression = trueExpression * piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression * threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = threeExpression * piExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + ASSERT_NO_THROW(tempExpression = intVarExpression * intConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + + ASSERT_THROW(tempExpression = trueExpression / piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression / threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = threeExpression / piExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + ASSERT_NO_THROW(tempExpression = doubleVarExpression / intConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + + ASSERT_THROW(tempExpression = trueExpression && piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = trueExpression && falseExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = boolVarExpression && boolConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression || piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = trueExpression || falseExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = boolVarExpression || boolConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = !threeExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = !trueExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = !boolVarExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression == piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression == threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = intVarExpression == doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression != piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression != threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = intVarExpression != doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression > piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression > threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = intVarExpression > doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression >= piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression >= threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = intVarExpression >= doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression < piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression < threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = intVarExpression < doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression <= piExpression, storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression <= threeExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = intVarExpression <= doubleConstExpression); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = storm::expressions::Expression::minimum(trueExpression, piExpression), storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::minimum(threeExpression, threeExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::minimum(intVarExpression, doubleConstExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + + ASSERT_THROW(tempExpression = storm::expressions::Expression::maximum(trueExpression, piExpression), storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::maximum(threeExpression, threeExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::maximum(intVarExpression, doubleConstExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double); + + ASSERT_THROW(tempExpression = trueExpression.implies(piExpression), storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = trueExpression.implies(falseExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = boolVarExpression.implies(boolConstExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression.iff(piExpression), storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = trueExpression.iff(falseExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + ASSERT_NO_THROW(tempExpression = boolVarExpression.iff(boolConstExpression)); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); + + ASSERT_THROW(tempExpression = trueExpression.floor(), storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression.floor()); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = doubleConstExpression.floor()); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + + ASSERT_THROW(tempExpression = trueExpression.ceil(), storm::exceptions::InvalidTypeException); + ASSERT_NO_THROW(tempExpression = threeExpression.ceil()); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); + ASSERT_NO_THROW(tempExpression = doubleConstExpression.ceil()); + EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); +} + +TEST(Expression, SubstitutionTest) { + storm::expressions::Expression trueExpression; + storm::expressions::Expression falseExpression; + storm::expressions::Expression threeExpression; + storm::expressions::Expression piExpression; + storm::expressions::Expression boolVarExpression; + storm::expressions::Expression intVarExpression; + storm::expressions::Expression doubleVarExpression; + storm::expressions::Expression boolConstExpression; + storm::expressions::Expression intConstExpression; + storm::expressions::Expression doubleConstExpression; + + ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue()); + ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse()); + ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3)); + ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14)); + ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x")); + ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y")); + ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z")); + ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a")); + ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b")); + ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c")); + + storm::expressions::Expression tempExpression; + ASSERT_NO_THROW(tempExpression = (intVarExpression < threeExpression || boolVarExpression) && boolConstExpression); + + std::map<std::string, storm::expressions::Expression> substution = { std::make_pair("y", doubleConstExpression), std::make_pair("x", storm::expressions::Expression::createTrue()), std::make_pair("a", storm::expressions::Expression::createTrue()) }; + storm::expressions::Expression substitutedExpression; + ASSERT_NO_THROW(substitutedExpression = tempExpression.substitute<std::map>(substution)); + EXPECT_TRUE(substitutedExpression.simplify().isTrue()); +} + +TEST(Expression, SimplificationTest) { + storm::expressions::Expression trueExpression; + storm::expressions::Expression falseExpression; + storm::expressions::Expression threeExpression; + storm::expressions::Expression intVarExpression; + + ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue()); + ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse()); + ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3)); + ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y")); + + storm::expressions::Expression tempExpression; + storm::expressions::Expression simplifiedExpression; + + ASSERT_NO_THROW(tempExpression = trueExpression || intVarExpression > threeExpression); + ASSERT_NO_THROW(simplifiedExpression = tempExpression.simplify()); + EXPECT_TRUE(simplifiedExpression.isTrue()); + + ASSERT_NO_THROW(tempExpression = falseExpression && intVarExpression > threeExpression); + ASSERT_NO_THROW(simplifiedExpression = tempExpression.simplify()); + EXPECT_TRUE(simplifiedExpression.isFalse()); +} + +TEST(Expression, SimpleEvaluationTest) { + storm::expressions::Expression trueExpression; + storm::expressions::Expression falseExpression; + storm::expressions::Expression threeExpression; + storm::expressions::Expression piExpression; + storm::expressions::Expression boolVarExpression; + storm::expressions::Expression intVarExpression; + storm::expressions::Expression doubleVarExpression; + storm::expressions::Expression boolConstExpression; + storm::expressions::Expression intConstExpression; + storm::expressions::Expression doubleConstExpression; + + ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue()); + ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse()); + ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3)); + ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14)); + ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x")); + ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y")); + ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z")); + ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a")); + ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b")); + ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c")); + + storm::expressions::Expression tempExpression; + + ASSERT_NO_THROW(tempExpression = (intVarExpression < threeExpression || boolVarExpression) && boolConstExpression); + + ASSERT_NO_THROW(storm::expressions::SimpleValuation valuation); + storm::expressions::SimpleValuation valuation; + ASSERT_NO_THROW(valuation.addBooleanIdentifier("x")); + ASSERT_NO_THROW(valuation.addBooleanIdentifier("a")); + ASSERT_NO_THROW(valuation.addIntegerIdentifier("y")); + ASSERT_NO_THROW(valuation.addIntegerIdentifier("b")); + ASSERT_NO_THROW(valuation.addDoubleIdentifier("z")); + ASSERT_NO_THROW(valuation.addDoubleIdentifier("c")); + + ASSERT_THROW(tempExpression.evaluateAsDouble(&valuation), storm::exceptions::InvalidTypeException); + ASSERT_THROW(tempExpression.evaluateAsInt(&valuation), storm::exceptions::InvalidTypeException); + EXPECT_FALSE(tempExpression.evaluateAsBool(&valuation)); + ASSERT_NO_THROW(valuation.setBooleanValue("a", true)); + EXPECT_TRUE(tempExpression.evaluateAsBool(&valuation)); + ASSERT_NO_THROW(valuation.setIntegerValue("y", 3)); + EXPECT_FALSE(tempExpression.evaluateAsBool(&valuation)); + + ASSERT_NO_THROW(tempExpression = ((intVarExpression < threeExpression).ite(trueExpression, falseExpression))); + ASSERT_THROW(tempExpression.evaluateAsDouble(&valuation), storm::exceptions::InvalidTypeException); + ASSERT_THROW(tempExpression.evaluateAsInt(&valuation), storm::exceptions::InvalidTypeException); + EXPECT_FALSE(tempExpression.evaluateAsBool(&valuation)); +} \ No newline at end of file