Browse Source

Added class for initial construct of PRISM programs (to capture position information). Added more validity checks for programs and tests for them (not all though).

Former-commit-id: cf4e985684
tempestpy_adaptions
dehnert 11 years ago
parent
commit
c76e0e8d4d
  1. 38
      src/parser/PrismParser.cpp
  2. 16
      src/parser/PrismParser.h
  3. 7
      src/storage/expressions/BaseExpression.cpp
  4. 4
      src/storage/expressions/SubstitutionVisitor.cpp
  5. 12
      src/storage/expressions/TypeCheckVisitor.cpp
  6. 2
      src/storage/prism/Command.cpp
  7. 4
      src/storage/prism/Constant.cpp
  8. 4
      src/storage/prism/Formula.cpp
  9. 24
      src/storage/prism/InitialConstruct.cpp
  10. 56
      src/storage/prism/InitialConstruct.h
  11. 4
      src/storage/prism/Label.cpp
  12. 4
      src/storage/prism/LocatedInformation.cpp
  13. 3
      src/storage/prism/Module.cpp
  14. 265
      src/storage/prism/Program.cpp
  15. 35
      src/storage/prism/Program.h
  16. 2
      src/storage/prism/Update.cpp
  17. 184
      test/functional/parser/PrismParserTest.cpp

38
src/parser/PrismParser.cpp

@ -5,7 +5,7 @@
namespace storm {
namespace parser {
storm::prism::Program PrismParser::parse(std::string const& filename, bool typeCheck) {
storm::prism::Program PrismParser::parse(std::string const& filename) {
// 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 << "'.");
@ -15,7 +15,7 @@ namespace storm {
// 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);
result = parseFromString(fileContent, filename);
} catch(std::exception& e) {
// In case of an exception properly close the file before passing exception.
inputFileStream.close();
@ -27,7 +27,7 @@ namespace storm {
return result;
}
storm::prism::Program PrismParser::parseFromString(std::string const& input, std::string const& filename, bool typeCheck) {
storm::prism::Program PrismParser::parseFromString(std::string const& input, std::string const& filename) {
PositionIteratorType first(input.begin());
PositionIteratorType iter = first;
PositionIteratorType last(input.end());
@ -38,17 +38,17 @@ namespace storm {
// 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.
// Start first run.
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.");
}
// Start second run.
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);
@ -162,7 +162,7 @@ namespace storm {
>> 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 = (qi::lit("init") > expression > qi::lit("endinit"))[qi::_pass = phoenix::bind(&PrismParser::addInitialStatesConstruct, 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)];
@ -264,13 +264,13 @@ namespace storm {
return true;
}
bool PrismParser::addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation) {
LOG_THROW(!globalProgramInformation.hasInitialStatesExpression, storm::exceptions::WrongFormatException, "Parsing error in " << this->getFilename() << ", line " << get_line(qi::_3) << ": Program must not define two initial constructs.");
if (globalProgramInformation.hasInitialStatesExpression) {
bool PrismParser::addInitialStatesConstruct(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation) {
LOG_THROW(!globalProgramInformation.hasInitialConstruct, storm::exceptions::WrongFormatException, "Parsing error in " << this->getFilename() << ", line " << get_line(qi::_3) << ": Program must not define two initial constructs.");
if (globalProgramInformation.hasInitialConstruct) {
return false;
}
globalProgramInformation.hasInitialStatesExpression = true;
globalProgramInformation.initialStatesExpression = initialStatesExpression;
globalProgramInformation.hasInitialConstruct = true;
globalProgramInformation.initialConstruct = storm::prism::InitialConstruct(initialStatesExpression, this->getFilename(), get_line(qi::_3));
return true;
}
@ -762,7 +762,7 @@ namespace storm {
}
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());
return storm::prism::Program(globalProgramInformation.modelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables, globalProgramInformation.globalIntegerVariables, globalProgramInformation.formulas, globalProgramInformation.modules, globalProgramInformation.rewardModels, this->secondRun && !globalProgramInformation.hasInitialConstruct, globalProgramInformation.initialConstruct, globalProgramInformation.labels, this->getFilename(), 1, this->secondRun);
}
} // namespace parser
} // namespace storm

16
src/parser/PrismParser.h

@ -35,7 +35,9 @@ namespace storm {
class GlobalProgramInformation {
public:
// Default construct the header information.
GlobalProgramInformation() : hasInitialStatesExpression(false), currentCommandIndex(0), currentUpdateIndex(0) {}
GlobalProgramInformation() : modelType(), constants(), formulas(), globalBooleanVariables(), globalIntegerVariables(), moduleToIndexMap(), modules(), rewardModels(), labels(),hasInitialConstruct(false), initialConstruct(storm::expressions::Expression::createFalse()), currentCommandIndex(0), currentUpdateIndex(0) {
// Intentionally left empty.
}
// Members for all essential information that needs to be collected.
storm::prism::Program::ModelType modelType;
@ -47,8 +49,8 @@ namespace storm {
std::vector<storm::prism::Module> modules;
std::vector<storm::prism::RewardModel> rewardModels;
std::vector<storm::prism::Label> labels;
storm::expressions::Expression initialStatesExpression;
bool hasInitialStatesExpression;
bool hasInitialConstruct;
storm::prism::InitialConstruct initialConstruct;
// Counters to provide unique indexing for commands and updates.
uint_fast64_t currentCommandIndex;
@ -61,20 +63,18 @@ namespace storm {
* 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);
static storm::prism::Program parse(std::string const& filename);
/*!
* 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);
static storm::prism::Program parseFromString(std::string const& input, std::string const& filename);
private:
struct modelTypeStruct : qi::symbols<char, storm::prism::Program::ModelType> {
@ -263,7 +263,7 @@ namespace storm {
// Helper methods used in the grammar.
bool isValidIdentifier(std::string const& identifier);
bool addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation);
bool addInitialStatesConstruct(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 createImpliesExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;

7
src/storage/expressions/BaseExpression.cpp

@ -53,7 +53,12 @@ namespace storm {
}
std::ostream& operator<<(std::ostream& stream, ExpressionReturnType const& enumValue) {
stream << static_cast<std::underlying_type<ExpressionReturnType>::type>(enumValue);
switch (enumValue) {
case ExpressionReturnType::Undefined: stream << "undefined"; break;
case ExpressionReturnType::Bool: stream << "bool"; break;
case ExpressionReturnType::Int: stream << "int"; break;
case ExpressionReturnType::Double: stream << "double"; break;
}
return stream;
}

4
src/storage/expressions/SubstitutionVisitor.cpp

@ -182,7 +182,7 @@ namespace storm {
}
// Explicitly instantiate the class with map and unordered_map.
template class SubstitutionVisitor< std::map<std::string, Expression> >;
template class SubstitutionVisitor< std::unordered_map<std::string, Expression> >;
template class SubstitutionVisitor<std::map<std::string, Expression>>;
template class SubstitutionVisitor<std::unordered_map<std::string, Expression>>;
}
}

12
src/storage/expressions/TypeCheckVisitor.cpp

@ -45,28 +45,28 @@ namespace storm {
void TypeCheckVisitor<MapType>::visit(BooleanConstantExpression const* expression) {
auto identifierTypePair = this->identifierToTypeMap.find(expression->getConstantName());
LOG_THROW(identifierTypePair != this->identifierToTypeMap.end(), storm::exceptions::InvalidArgumentException, "No type available for identifier '" << expression->getConstantName() << "'.");
LOG_THROW(identifierTypePair->second == ExpressionReturnType::Bool, storm::exceptions::InvalidTypeException, "Type mismatch for constant '" << expression->getConstantName() << "': expected bool, but found " << expression->getReturnType() << ".");
LOG_THROW(identifierTypePair->second == ExpressionReturnType::Bool, storm::exceptions::InvalidTypeException, "Type mismatch for constant '" << expression->getConstantName() << "': expected 'bool', but found '" << expression->getReturnType() << "'.");
}
template<typename MapType>
void TypeCheckVisitor<MapType>::visit(DoubleConstantExpression const* expression) {
auto identifierTypePair = this->identifierToTypeMap.find(expression->getConstantName());
LOG_THROW(identifierTypePair != this->identifierToTypeMap.end(), storm::exceptions::InvalidArgumentException, "No type available for identifier '" << expression->getConstantName() << "'.");
LOG_THROW(identifierTypePair->second == ExpressionReturnType::Bool, storm::exceptions::InvalidTypeException, "Type mismatch for constant '" << expression->getConstantName() << "': expected double, but found " << expression->getReturnType() << ".");
LOG_THROW(identifierTypePair->second == ExpressionReturnType::Double, storm::exceptions::InvalidTypeException, "Type mismatch for constant '" << expression->getConstantName() << "': expected 'double', but found '" << expression->getReturnType() << "'.");
}
template<typename MapType>
void TypeCheckVisitor<MapType>::visit(IntegerConstantExpression const* expression) {
auto identifierTypePair = this->identifierToTypeMap.find(expression->getConstantName());
LOG_THROW(identifierTypePair != this->identifierToTypeMap.end(), storm::exceptions::InvalidArgumentException, "No type available for identifier '" << expression->getConstantName() << "'.");
LOG_THROW(identifierTypePair->second == ExpressionReturnType::Bool, storm::exceptions::InvalidTypeException, "Type mismatch for constant '" << expression->getConstantName() << "': expected int, but found " << expression->getReturnType() << ".");
LOG_THROW(identifierTypePair->second == ExpressionReturnType::Int, storm::exceptions::InvalidTypeException, "Type mismatch for constant '" << expression->getConstantName() << "': expected 'int', but found '" << expression->getReturnType() << "'.");
}
template<typename MapType>
void TypeCheckVisitor<MapType>::visit(VariableExpression const* expression) {
auto identifierTypePair = this->identifierToTypeMap.find(expression->getVariableName());
LOG_THROW(identifierTypePair != this->identifierToTypeMap.end(), storm::exceptions::InvalidArgumentException, "No type available for identifier '" << expression->getVariableName() << "'.");
LOG_THROW(identifierTypePair->second == ExpressionReturnType::Bool, storm::exceptions::InvalidTypeException, "Type mismatch for variable '" << expression->getVariableName() << "': expected " << identifierTypePair->first << ", but found " << expression->getReturnType() << ".");
LOG_THROW(identifierTypePair->second == expression->getReturnType(), storm::exceptions::InvalidTypeException, "Type mismatch for variable '" << expression->getVariableName() << "': expected '" << identifierTypePair->first << "', but found '" << expression->getReturnType() << "'.");
}
template<typename MapType>
@ -93,5 +93,9 @@ namespace storm {
void TypeCheckVisitor<MapType>::visit(DoubleLiteralExpression const* expression) {
// Intentionally left empty.
}
// Explicitly instantiate the class with map and unordered_map.
template class TypeCheckVisitor<std::map<std::string, ExpressionReturnType>>;
template class TypeCheckVisitor<std::unordered_map<std::string, ExpressionReturnType>>;
}
}

2
src/storage/prism/Command.cpp

@ -51,5 +51,5 @@ namespace storm {
stream << ";";
return stream;
}
} // namespace ir
} // namespace prism
} // namespace storm

4
src/storage/prism/Constant.cpp

@ -48,5 +48,5 @@ namespace storm {
stream << ";";
return stream;
}
}
}
} // namespace prism
} // namespace storm

4
src/storage/prism/Formula.cpp

@ -26,5 +26,5 @@ namespace storm {
stream << "formula " << formula.getName() << " = " << formula.getExpression() << ";";
return stream;
}
}
}
} // namespace prism
} // namespace storm

24
src/storage/prism/InitialConstruct.cpp

@ -0,0 +1,24 @@
#include "src/storage/prism/InitialConstruct.h"
namespace storm {
namespace prism {
InitialConstruct::InitialConstruct(storm::expressions::Expression initialStatesExpression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), initialStatesExpression(initialStatesExpression) {
// Intentionally left empty.
}
storm::expressions::Expression InitialConstruct::getInitialStatesExpression() const {
return this->initialStatesExpression;
}
InitialConstruct InitialConstruct::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
return InitialConstruct(this->getInitialStatesExpression().substitute(substitution));
}
std::ostream& operator<<(std::ostream& stream, InitialConstruct const& initialConstruct) {
stream << "initial " << std::endl;
stream << "\t" << initialConstruct.getInitialStatesExpression() << std::endl;
stream << "endinitial" << std::endl;
return stream;
}
} // namespace prism
} // namespace storm

56
src/storage/prism/InitialConstruct.h

@ -0,0 +1,56 @@
#ifndef STORM_STORAGE_PRISM_INITIALCONSTRUCT_H_
#define STORM_STORAGE_PRISM_INITIALCONSTRUCT_H_
#include <string>
#include "src/storage/prism/LocatedInformation.h"
#include "src/storage/expressions/Expression.h"
#include "src/utility/OsDetection.h"
namespace storm {
namespace prism {
class InitialConstruct : public LocatedInformation {
public:
/*!
* Creates an initial construct with the given expression.
*
* @param initialStatesExpression An expression characterizing the initial states.
* @param filename The filename in which the command is defined.
* @param lineNumber The line number in which the command is defined.
*/
InitialConstruct(storm::expressions::Expression initialStatesExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
// Create default implementations of constructors/assignment.
InitialConstruct() = default;
InitialConstruct(InitialConstruct const& other) = default;
InitialConstruct& operator=(InitialConstruct const& other)= default;
#ifndef WINDOWS
InitialConstruct(InitialConstruct&& other) = default;
InitialConstruct& operator=(InitialConstruct&& other) = default;
#endif
/*!
* Retrieves the expression characterizing the initial states.
*
* @return The expression characterizing the initial states.
*/
storm::expressions::Expression getInitialStatesExpression() const;
/*!
* Substitutes all identifiers in the constant according to the given map.
*
* @param substitution The substitution to perform.
* @return The resulting initial construct.
*/
InitialConstruct substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
friend std::ostream& operator<<(std::ostream& stream, InitialConstruct const& initialConstruct);
private:
// An expression characterizing the initial states.
storm::expressions::Expression initialStatesExpression;
};
}
}
#endif /* STORM_STORAGE_PRISM_INITIALCONSTRUCT_H_ */

4
src/storage/prism/Label.cpp

@ -22,5 +22,5 @@ namespace storm {
stream << "label \"" << label.getName() << "\" = " << label.getStatePredicateExpression() << ";";
return stream;
}
}
}
} // namespace prism
} // namespace storm

4
src/storage/prism/LocatedInformation.cpp

@ -21,5 +21,5 @@ namespace storm {
void LocatedInformation::setLineNumber(uint_fast64_t lineNumber) {
this->lineNumber = lineNumber;
}
}
}
} // namespace prism
} // namespace storm

3
src/storage/prism/Module.cpp

@ -182,7 +182,6 @@ namespace storm {
stream << "endmodule" << std::endl;
return stream;
}
} // namespace ir
} // namespace prism
} // namespace storm

265
src/storage/prism/Program.cpp

@ -6,13 +6,41 @@
#include "exceptions/InvalidArgumentException.h"
#include "src/exceptions/OutOfRangeException.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/exceptions/InvalidTypeException.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() {
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 fixInitialConstruct, storm::prism::InitialConstruct const& initialConstruct, std::vector<Label> const& labels, std::string const& filename, uint_fast64_t lineNumber, bool checkValidity) : LocatedInformation(filename, lineNumber), modelType(modelType), constants(constants), constantToIndexMap(), globalBooleanVariables(globalBooleanVariables), globalBooleanVariableToIndexMap(), globalIntegerVariables(globalIntegerVariables), globalIntegerVariableToIndexMap(), formulas(formulas), formulaToIndexMap(), modules(modules), moduleToIndexMap(), rewardModels(rewardModels), rewardModelToIndexMap(), initialConstruct(initialConstruct), labels(labels), labelToIndexMap(), actions(), actionsToModuleIndexMap(), variableToModuleIndexMap() {
this->createMappings();
// Create a new initial construct if none was given explicitly.
if (fixInitialConstruct) {
if (this->getInitialConstruct().getInitialStatesExpression().isFalse()) {
storm::expressions::Expression newInitialExpression = storm::expressions::Expression::createTrue();
for (auto const& booleanVariable : this->getGlobalBooleanVariables()) {
newInitialExpression = newInitialExpression && (storm::expressions::Expression::createBooleanVariable(booleanVariable.getName()).iff(booleanVariable.getInitialValueExpression()));
}
for (auto const& integerVariable : this->getGlobalIntegerVariables()) {
newInitialExpression = newInitialExpression && (storm::expressions::Expression::createIntegerVariable(integerVariable.getName()) == integerVariable.getInitialValueExpression());
}
for (auto const& module : this->getModules()) {
for (auto const& booleanVariable : module.getBooleanVariables()) {
newInitialExpression = newInitialExpression && (storm::expressions::Expression::createBooleanVariable(booleanVariable.getName()).iff(booleanVariable.getInitialValueExpression()));
}
for (auto const& integerVariable : module.getIntegerVariables()) {
newInitialExpression = newInitialExpression && (storm::expressions::Expression::createIntegerVariable(integerVariable.getName()) == integerVariable.getInitialValueExpression());
}
}
this->initialConstruct = storm::prism::InitialConstruct(newInitialExpression, this->getInitialConstruct().getFilename(), this->getInitialConstruct().getLineNumber());
}
}
if (checkValidity) {
this->checkValidity();
}
}
Program::ModelType Program::getModelType() const {
return modelType;
}
@ -97,28 +125,8 @@ namespace storm {
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;
}
storm::prism::InitialConstruct const& Program::getInitialConstruct() const {
return this->initialConstruct;
}
std::set<std::string> const& Program::getActions() const {
@ -167,7 +175,7 @@ namespace storm {
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());
return Program(this->getModelType(), this->getConstants(), this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), newModules, this->getRewardModels(), false, this->getInitialConstruct(), this->getLabels());
}
void Program::createMappings() {
@ -259,7 +267,7 @@ namespace storm {
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());
return Program(this->getModelType(), newConstants, this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), this->getModules(), this->getRewardModels(), false, this->getInitialConstruct(), this->getLabels());
}
Program Program::substituteConstants() const {
@ -310,7 +318,7 @@ namespace storm {
newRewardModels.emplace_back(rewardModel.substitute(constantSubstitution));
}
storm::expressions::Expression newInitialStateExpression = this->getInitialStatesExpression().substitute(constantSubstitution);
storm::prism::InitialConstruct newInitialConstruct = this->getInitialConstruct().substitute(constantSubstitution);
std::vector<Label> newLabels;
newLabels.reserve(this->getNumberOfLabels());
@ -318,7 +326,7 @@ namespace storm {
newLabels.emplace_back(label.substitute(constantSubstitution));
}
return Program(this->getModelType(), newConstants, newBooleanVariables, newIntegerVariables, newFormulas, newModules, newRewardModels, this->definesInitialStatesExpression(), newInitialStateExpression, newLabels);
return Program(this->getModelType(), newConstants, newBooleanVariables, newIntegerVariables, newFormulas, newModules, newRewardModels, false, newInitialConstruct, newLabels);
}
void Program::checkValidity() const {
@ -327,6 +335,7 @@ namespace storm {
// Start by checking the constant declarations.
std::set<std::string> allIdentifiers;
std::set<std::string> globalIdentifiers;
std::set<std::string> constantNames;
for (auto const& constant : this->getConstants()) {
// Check for duplicate identifiers.
@ -340,9 +349,12 @@ namespace storm {
bool isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstantNames.begin(), containedConstantNames.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << constant.getFilename() << ", line " << constant.getLineNumber() << ": defining expression refers to unknown constants.");
// Now check that the constants appear with the right types (this throws an exception if this is not
// the case).
constant.getExpression().check(identifierToTypeMap);
// Now check that the constants appear with the right types.
try {
constant.getExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << constant.getFilename() << ", line " << constant.getLineNumber() << ": " << e.what());
}
}
// Finally, register the type of the constant for later type checks.
@ -351,6 +363,7 @@ namespace storm {
// Record the new identifier for future checks.
constantNames.insert(constant.getName());
allIdentifiers.insert(constant.getName());
globalIdentifiers.insert(constant.getName());
}
// Now we check the variable declarations. We start with the global variables.
@ -364,7 +377,11 @@ namespace storm {
std::set<std::string> containedConstants = variable.getInitialValueExpression().getConstants();
bool isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants.");
try {
variable.getInitialValueExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
// Register the type of the constant for later type checks.
identifierToTypeMap.emplace(variable.getName(), storm::expressions::ExpressionReturnType::Bool);
@ -372,6 +389,7 @@ namespace storm {
// Record the new identifier for future checks.
variableNames.insert(variable.getName());
allIdentifiers.insert(variable.getName());
globalIdentifiers.insert(variable.getName());
}
for (auto const& variable : this->getGlobalIntegerVariables()) {
// Check for duplicate identifiers.
@ -382,19 +400,32 @@ namespace storm {
std::set<std::string> containedConstants = variable.getLowerBoundExpression().getConstants();
bool isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": lower bound expression refers to unknown constants.");
variable.getLowerBoundExpression().check(identifierToTypeMap);
try {
variable.getLowerBoundExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
LOG_THROW(variable.getUpperBoundExpression().getVariables().empty(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": upper bound expression must not refer to variables.");
containedConstants = variable.getLowerBoundExpression().getConstants();
isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": upper bound expression refers to unknown constants.");
variable.getUpperBoundExpression().check(identifierToTypeMap);
try {
variable.getUpperBoundExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
// Check the initial value of the variable.
LOG_THROW(variable.getInitialValueExpression().getVariables().empty(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression must not refer to variables.");
containedConstants = variable.getInitialValueExpression().getConstants();
isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants.");
variable.getInitialValueExpression().check(identifierToTypeMap);
try {
variable.getInitialValueExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
// Register the type of the constant for later type checks.
identifierToTypeMap.emplace(variable.getName(), storm::expressions::ExpressionReturnType::Int);
@ -402,6 +433,7 @@ namespace storm {
// Record the new identifier for future checks.
variableNames.insert(variable.getName());
allIdentifiers.insert(variable.getName());
globalIdentifiers.insert(variable.getName());
}
// Now go through the variables of the modules.
@ -415,7 +447,11 @@ namespace storm {
std::set<std::string> containedConstants = variable.getInitialValueExpression().getConstants();
bool isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants.");
variable.getInitialValueExpression().check(identifierToTypeMap);
try {
variable.getInitialValueExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
// Register the type of the constant for later type checks.
identifierToTypeMap.emplace(variable.getName(), storm::expressions::ExpressionReturnType::Bool);
@ -436,19 +472,32 @@ namespace storm {
std::set<std::string> containedConstants = variable.getLowerBoundExpression().getConstants();
bool isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": lower bound expression refers to unknown constants.");
variable.getLowerBoundExpression().check(identifierToTypeMap);
try {
variable.getLowerBoundExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
LOG_THROW(variable.getUpperBoundExpression().getVariables().empty(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": upper bound expression must not refer to variables.");
containedConstants = variable.getLowerBoundExpression().getConstants();
isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": upper bound expression refers to unknown constants.");
variable.getUpperBoundExpression().check(identifierToTypeMap);
try {
variable.getUpperBoundExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
// Check the initial value of the variable.
LOG_THROW(variable.getInitialValueExpression().getVariables().empty(), storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression must not refer to variables.");
containedConstants = variable.getInitialValueExpression().getConstants();
isValid = std::includes(constantNames.begin(), constantNames.end(), containedConstants.begin(), containedConstants.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": initial value expression refers to unknown constants.");
variable.getInitialValueExpression().check(identifierToTypeMap);
try {
variable.getInitialValueExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << variable.getFilename() << ", line " << variable.getLineNumber() << ": " << e.what());
}
// Record the new identifier for future checks.
variableNames.insert(variable.getName());
@ -460,16 +509,124 @@ namespace storm {
std::set<std::string> variablesAndConstants;
std::set_union(variableNames.begin(), variableNames.end(), constantNames.begin(), constantNames.end(), std::inserter(variablesAndConstants, variablesAndConstants.begin()));
// TODO: check commands.
// Check the commands of the modules.
for (auto const& module : this->getModules()) {
std::set<std::string> legalIdentifiers = globalIdentifiers;
for (auto const& variable : module.getBooleanVariables()) {
legalIdentifiers.insert(variable.getName());
}
for (auto const& variable : module.getIntegerVariables()) {
legalIdentifiers.insert(variable.getName());
}
for (auto const& command : module.getCommands()) {
// Check the guard.
std::set<std::string> containedIdentifiers = command.getGuardExpression().getIdentifiers();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": guard refers to unknown identifiers.");
try {
command.getGuardExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": " << e.what());
}
LOG_THROW(command.getGuardExpression().hasBooleanReturnType(), storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": expression for guard must evaluate to type 'bool'.");
// Check all updates.
for (auto const& update : command.getUpdates()) {
containedIdentifiers = update.getLikelihoodExpression().getIdentifiers();
isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": likelihood expression refers to unknown identifiers.");
try {
update.getLikelihoodExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": " << e.what());
}
// Check all assignments.
std::set<std::string> alreadyAssignedIdentifiers;
for (auto const& assignment : update.getAssignments()) {
if (legalIdentifiers.find(assignment.getVariableName()) == legalIdentifiers.end()) {
if (allIdentifiers.find(assignment.getVariableName()) != allIdentifiers.end()) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": assignment illegally refers to variable '" << assignment.getVariableName() << "'.");
} else {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": assignment refers to unknown variable '" << assignment.getVariableName() << "'.");
}
}
LOG_THROW(alreadyAssignedIdentifiers.find(assignment.getVariableName()) == alreadyAssignedIdentifiers.end(), storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": duplicate assignment to variable '" << assignment.getVariableName() << "'.");
auto variableTypePair = identifierToTypeMap.find(assignment.getVariableName());
LOG_THROW(variableTypePair->second == assignment.getExpression().getReturnType(), storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": illegally assigning a value of type '" << assignment.getExpression().getReturnType() << "' to variable '" << variableTypePair->first << "' of type '" << variableTypePair->second << "'.");
containedIdentifiers = assignment.getExpression().getIdentifiers();
isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": likelihood expression refers to unknown identifiers.");
try {
assignment.getExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": " << e.what());
}
// Add the current variable to the set of assigned variables (of this update).
alreadyAssignedIdentifiers.insert(assignment.getVariableName());
}
}
}
}
// TODO: check reward models.
// Now check the reward models.
for (auto const& rewardModel : this->getRewardModels()) {
for (auto const& stateReward : rewardModel.getStateRewards()) {
std::set<std::string> containedIdentifiers = stateReward.getStatePredicateExpression().getIdentifiers();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << stateReward.getFilename() << ", line " << stateReward.getLineNumber() << ": state reward expression refers to unknown identifiers.");
try {
stateReward.getStatePredicateExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << stateReward.getFilename() << ", line " << stateReward.getLineNumber() << ": " << e.what());
}
LOG_THROW(stateReward.getStatePredicateExpression().hasBooleanReturnType(), storm::exceptions::WrongFormatException, "Error in " << stateReward.getFilename() << ", line " << stateReward.getLineNumber() << ": state predicate must evaluate to type 'bool'.");
containedIdentifiers = stateReward.getRewardValueExpression().getIdentifiers();
isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << stateReward.getFilename() << ", line " << stateReward.getLineNumber() << ": state reward value expression refers to unknown identifiers.");
try {
stateReward.getRewardValueExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << stateReward.getFilename() << ", line " << stateReward.getLineNumber() << ": " << e.what());
}
LOG_THROW(stateReward.getRewardValueExpression().hasNumericalReturnType(), storm::exceptions::WrongFormatException, "Error in " << stateReward.getFilename() << ", line " << stateReward.getLineNumber() << ": reward value expression must evaluate to numerical type.");
}
for (auto const& transitionReward : rewardModel.getTransitionRewards()) {
std::set<std::string> containedIdentifiers = transitionReward.getStatePredicateExpression().getIdentifiers();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << transitionReward.getFilename() << ", line " << transitionReward.getLineNumber() << ": state reward expression refers to unknown identifiers.");
try {
transitionReward.getStatePredicateExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << transitionReward.getFilename() << ", line " << transitionReward.getLineNumber() << ": " << e.what());
}
LOG_THROW(transitionReward.getStatePredicateExpression().hasBooleanReturnType(), storm::exceptions::WrongFormatException, "Error in " << transitionReward.getFilename() << ", line " << transitionReward.getLineNumber() << ": state predicate must evaluate to type 'bool'.");
containedIdentifiers = transitionReward.getRewardValueExpression().getIdentifiers();
isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << transitionReward.getFilename() << ", line " << transitionReward.getLineNumber() << ": state reward value expression refers to unknown identifiers.");
try {
transitionReward.getRewardValueExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << transitionReward.getFilename() << ", line " << transitionReward.getLineNumber() << ": " << e.what());
}
LOG_THROW(transitionReward.getRewardValueExpression().hasNumericalReturnType(), storm::exceptions::WrongFormatException, "Error in " << transitionReward.getFilename() << ", line " << transitionReward.getLineNumber() << ": reward value expression must evaluate to numerical type.");
}
}
// Check the initial states expression (if the program defines it).
if (this->hasInitialStatesExpression) {
std::set<std::string> containedIdentifiers = this->initialStatesExpression.getIdentifiers();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << this->getFilename() << ", line " << this->getLineNumber() << ": initial expression refers to unknown identifiers.");
this->initialStatesExpression.check(identifierToTypeMap);
// Check the initial states expression.
std::set<std::string> containedIdentifiers = this->getInitialConstruct().getInitialStatesExpression().getIdentifiers();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << this->getInitialConstruct().getFilename() << ", line " << this->getInitialConstruct().getLineNumber() << ": initial expression refers to unknown identifiers.");
try {
this->getInitialConstruct().getInitialStatesExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << this->getInitialConstruct().getFilename() << ", line " << this->getInitialConstruct().getLineNumber() << ": " << e.what());
}
// Check the labels.
@ -480,7 +637,13 @@ namespace storm {
std::set<std::string> containedIdentifiers = label.getStatePredicateExpression().getIdentifiers();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << label.getFilename() << ", line " << label.getLineNumber() << ": label expression refers to unknown identifiers.");
label.getStatePredicateExpression().check(identifierToTypeMap);
try {
label.getStatePredicateExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << label.getFilename() << ", line " << label.getLineNumber() << ": " << e.what());
}
LOG_THROW(label.getStatePredicateExpression().hasBooleanReturnType(), storm::exceptions::WrongFormatException, "Error in " << label.getFilename() << ", line " << label.getLineNumber() << ": label predicate must evaluate to type 'bool'.");
}
// Check the formulas.
@ -491,7 +654,11 @@ namespace storm {
std::set<std::string> containedIdentifiers = formula.getExpression().getIdentifiers();
bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedIdentifiers.begin(), containedIdentifiers.end());
LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << formula.getFilename() << ", line " << formula.getLineNumber() << ": formula expression refers to unknown identifiers.");
formula.getExpression().check(identifierToTypeMap);
try {
formula.getExpression().check(identifierToTypeMap);
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << formula.getFilename() << ", line " << formula.getLineNumber() << ": " << e.what());
}
// Record the new identifier for future checks.
allIdentifiers.insert(formula.getName());
@ -542,5 +709,5 @@ namespace storm {
return stream;
}
} // namespace ir
} // namespace prism
} // namepsace storm

35
src/storage/prism/Program.h

@ -12,6 +12,7 @@
#include "src/storage/prism/Label.h"
#include "src/storage/prism/Module.h"
#include "src/storage/prism/RewardModel.h"
#include "src/storage/prism/InitialConstruct.h"
#include "src/utility/OsDetection.h"
namespace storm {
@ -33,17 +34,18 @@ namespace storm {
* @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 fixInitialConstruct A flag that indicates whether the given initial construct is to be ignored and
* replaced by a new one created from the initial values of the variables.
* @param initialConstruct The initial construct of the program. If the initial construct specifies "false"
* as the initial condition, the default values of the variables are used to construct a legal initial
* condition.
* @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.
* @param checkValidity If set to true, the program is checked for validity.
*/
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);
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 fixInitialConstruct, storm::prism::InitialConstruct const& initialConstruct, std::vector<Label> const& labels, std::string const& filename = "", uint_fast64_t lineNumber = 0, bool checkValidity = true);
// Provide default implementations for constructors and assignments.
Program() = default;
@ -187,18 +189,11 @@ namespace storm {
std::vector<Module> const& getModules() const;
/*!
* Retrieves whether the program explicitly specifies an expression characterizing the initial states.
* Retrieves the initial construct of the program.
*
* @return True iff the program specifies an expression defining the initial states.
* @return The initial construct of the program.
*/
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;
storm::prism::InitialConstruct const& getInitialConstruct() const;
/*!
* Retrieves the set of actions present in the program.
@ -336,12 +331,8 @@ namespace storm {
// 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 initial construct of the program.
storm::prism::InitialConstruct initialConstruct;
// The labels that are defined for this model.
std::vector<Label> labels;

2
src/storage/prism/Update.cpp

@ -60,5 +60,5 @@ namespace storm {
return stream;
}
} // namespace ir
} // namespace prism
} // namespace storm

184
test/functional/parser/PrismParserTest.cpp

@ -2,47 +2,20 @@
#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) {
TEST(PrismParser, StandardModelTest) {
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));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/crowds5_5.pm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/csma2_2.nm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/die.pm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/firewire.nm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3.nm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3_5.pm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/two_dice.nm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/wlan0_collide.nm"));
}
TEST(PrismParser, SimpleFullTest) {
TEST(PrismParser, SimpleTest) {
std::string testInput =
R"(dtmc
module mod1
@ -51,7 +24,7 @@ TEST(PrismParser, SimpleFullTest) {
endmodule)";
storm::prism::Program result;
EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", true));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"));
EXPECT_EQ(1, result.getNumberOfModules());
EXPECT_EQ(storm::prism::Program::ModelType::DTMC, result.getModelType());
@ -66,12 +39,12 @@ TEST(PrismParser, SimpleFullTest) {
[] x=3 -> 1:(x'=4);
[] x=4 -> 1:(x'=5);
endmodule)";
EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", true));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"));
EXPECT_EQ(1, result.getNumberOfModules());
EXPECT_EQ(storm::prism::Program::ModelType::MDP, result.getModelType());
}
TEST(PrismParser, ComplexFullTest) {
TEST(PrismParser, ComplexTest) {
std::string testInput =
R"(ma
@ -94,11 +67,11 @@ TEST(PrismParser, ComplexFullTest) {
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);
[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));
[b] (k > 3) & false & (min(a, 0) < max(h, k)) -> 1-e: (g'=(1-a) * 2 + floor(f) > 2);
endmodule
module mod3 = mod1 [ i = i1, j = j1, k = k1 ] endmodule
@ -120,68 +93,11 @@ TEST(PrismParser, ComplexFullTest) {
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);
result = storm::parser::PrismParser::parseFromString(testInput, "testfile");
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, IllegalInputTest) {
@ -198,7 +114,7 @@ TEST(PrismParser, IllegalInputTest) {
)";
storm::prism::Program result;
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false), storm::exceptions::WrongFormatException);
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
@ -210,7 +126,7 @@ TEST(PrismParser, IllegalInputTest) {
[] a < 3 -> 1: (a' = a+1);
endmodule)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false), storm::exceptions::WrongFormatException);
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
@ -223,7 +139,7 @@ TEST(PrismParser, IllegalInputTest) {
[] c < 3 -> 1: (c' = c+1);
endmodule)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false), storm::exceptions::WrongFormatException);
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
@ -245,5 +161,63 @@ TEST(PrismParser, IllegalInputTest) {
)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false), storm::exceptions::WrongFormatException);
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
module mod1
c : [0 .. 8] init 1;
[] c < 3 -> 1: (c' = c+1);
endmodule
module mod2
[] c < 3 -> 1: (c' = c+1);
endmodule)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
module mod1
c : [0 .. 8] init 1;
[] c < 3 -> 1: (c' = c+1)&(c'=c-1);
endmodule)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
module mod1
c : [0 .. 8] init 1;
[] c < 3 -> 1: (c' = true || false);
endmodule)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
module mod1
c : [0 .. 8] init 1;
[] c + 3 -> 1: (c' = 1);
endmodule)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
testInput =
R"(dtmc
module mod1
c : [0 .. 8] init 1;
[] c + 3 -> 1: (c' = 1);
endmodule
label "test" = c + 1;
)";
EXPECT_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"), storm::exceptions::WrongFormatException);
}
Loading…
Cancel
Save