diff --git a/src/models/sparse/Mdp.cpp b/src/models/sparse/Mdp.cpp index 1c8bd1b50..469dfe54e 100644 --- a/src/models/sparse/Mdp.cpp +++ b/src/models/sparse/Mdp.cpp @@ -72,9 +72,21 @@ namespace storm { this->hasStateRewards() ? boost::optional<std::vector<ValueType>>(this->getStateRewardVector()) : boost::optional<std::vector<ValueType>>(), this->hasTransitionRewards() ? boost::optional<storm::storage::SparseMatrix<ValueType>>(this->getTransitionRewardMatrix()) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), boost::optional<std::vector<LabelSet>>(newChoiceLabeling)); + return restrictedMdp; } + template <typename ValueType> + Mdp<ValueType> Mdp<ValueType>::restrictActions(storm::storage::BitVector const& enabledActions) const { + storm::storage::SparseMatrix<ValueType> restrictedTransitions = this->getTransitionMatrix().restrictRows(enabledActions); + if(this->hasTransitionRewards()) { + return Mdp<ValueType>(restrictedTransitions, this->getStateLabeling(), this->getOptionalStateRewardVector(), boost::optional<storm::storage::SparseMatrix<ValueType>>(this->getTransitionRewardMatrix().restrictRows(enabledActions)), this->getOptionalChoiceLabeling()); + } else { + return Mdp<ValueType>( restrictedTransitions, this->getStateLabeling(), this->getOptionalStateRewardVector(), boost::optional<storm::storage::SparseMatrix<ValueType>>(), this->getOptionalChoiceLabeling()); + } + + } + template <typename ValueType> bool Mdp<ValueType>::checkValidityOfProbabilityMatrix() const { storm::utility::ConstantsComparator<ValueType> comparator; diff --git a/src/models/sparse/Mdp.h b/src/models/sparse/Mdp.h index 18879ee76..3b66d0e61 100644 --- a/src/models/sparse/Mdp.h +++ b/src/models/sparse/Mdp.h @@ -63,6 +63,14 @@ namespace storm { */ Mdp<ValueType> restrictChoiceLabels(LabelSet const& enabledChoiceLabels) const; + /*! + * Constructs an MDP by copying the current MDP and restricting the choices of each state to the ones given by the bitvector. + * + * @param enabledActions A BitVector of lenght numberOfChoices(), which is one iff the action should be kept. + * @return A subMDP. + */ + Mdp<ValueType> restrictActions(storm::storage::BitVector const& enabledActions) const; + private: /*! * Checks the probability matrix for validity. diff --git a/src/models/sparse/Model.cpp b/src/models/sparse/Model.cpp index b2ca03c1d..506083cbc 100644 --- a/src/models/sparse/Model.cpp +++ b/src/models/sparse/Model.cpp @@ -113,6 +113,11 @@ namespace storm { return choiceLabeling.get(); } + template <typename ValueType> + boost::optional<std::vector<LabelSet>> const& Model<ValueType>::getOptionalChoiceLabeling() const { + return choiceLabeling; + } + template <typename ValueType> storm::models::sparse::StateLabeling const& Model<ValueType>::getStateLabeling() const { return stateLabeling; diff --git a/src/models/sparse/Model.h b/src/models/sparse/Model.h index 5457370e6..4d1901d1f 100644 --- a/src/models/sparse/Model.h +++ b/src/models/sparse/Model.h @@ -173,13 +173,20 @@ namespace storm { boost::optional<std::vector<ValueType>> const& getOptionalStateRewardVector() const; /*! - * Retrieves the labels for the choices of the model. Note that calling this method is only valud if the - * model has a choice labling. + * Retrieves the labels for the choices of the model. Note that calling this method is only valid if the + * model has a choice labeling. * * @return The labels for the choices of the model. */ std::vector<LabelSet> const& getChoiceLabeling() const; + /*! + * Retrieves an optional value that contains the choice labeling if there is one. + * + * @return The labels for the choices, if they're saved. + */ + boost::optional<std::vector<LabelSet>> const& getOptionalChoiceLabeling() const; + /*! * Returns the state labeling associated with this model. * @@ -194,6 +201,7 @@ namespace storm { */ storm::models::sparse::StateLabeling& getStateLabeling(); + /*! * Retrieves whether this model has state rewards. * diff --git a/src/storage/SparseMatrix.cpp b/src/storage/SparseMatrix.cpp index ce5419099..2cb9f995b 100644 --- a/src/storage/SparseMatrix.cpp +++ b/src/storage/SparseMatrix.cpp @@ -614,6 +614,14 @@ namespace storm { return matrixBuilder.build(); } + template<typename ValueType> + SparseMatrix<ValueType> SparseMatrix<ValueType>::restrictRows(storm::storage::BitVector const& rowsToKeep) const { + // For now, we use the expensive call to submatrix. + SparseMatrix<ValueType> res(getSubmatrix(false, rowsToKeep, storm::storage::BitVector(getColumnCount(), true), false)); + assert(getRowGroupCount() == res.getRowGroupCount()); + return res; + } + template<typename ValueType> SparseMatrix<ValueType> SparseMatrix<ValueType>::selectRowsFromRowGroups(std::vector<index_type> const& rowGroupToRowIndexMapping, bool insertDiagonalEntries) const { // First, we need to count how many non-zero entries the resulting matrix will have and reserve space for diff --git a/src/storage/SparseMatrix.h b/src/storage/SparseMatrix.h index 35ff09658..7d7092377 100644 --- a/src/storage/SparseMatrix.h +++ b/src/storage/SparseMatrix.h @@ -610,6 +610,14 @@ namespace storm { */ SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const& rowConstraint, storm::storage::BitVector const& columnConstraint, bool insertDiagonalEntries = false) const; + /*! + * Restrict rows in grouped rows matrix. Ensures that the number of groups stays the same. + * + * @param rowsToKeep A bit vector indicating which rows to keep. + * + */ + SparseMatrix restrictRows(storm::storage::BitVector const& rowsToKeep) const; + /*! * Selects exactly one row from each row group of this matrix and returns the resulting matrix. * diff --git a/src/storage/expressions/IfThenElseExpression.cpp b/src/storage/expressions/IfThenElseExpression.cpp index f3e65a94f..4692675bf 100644 --- a/src/storage/expressions/IfThenElseExpression.cpp +++ b/src/storage/expressions/IfThenElseExpression.cpp @@ -70,7 +70,7 @@ namespace storm { } std::shared_ptr<BaseExpression const> IfThenElseExpression::simplify() const { - std::shared_ptr<BaseExpression const> conditionSimplified; + std::shared_ptr<BaseExpression const> conditionSimplified = this->condition->simplify(); if (conditionSimplified->isTrue()) { return this->thenExpression->simplify(); } else if (conditionSimplified->isFalse()) { diff --git a/src/storage/prism/Program.cpp b/src/storage/prism/Program.cpp index 0b61fd795..3792bea94 100644 --- a/src/storage/prism/Program.cpp +++ b/src/storage/prism/Program.cpp @@ -12,7 +12,16 @@ namespace storm { namespace prism { - Program::Program(std::shared_ptr<storm::expressions::ExpressionManager> manager, 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::map<std::string, uint_fast64_t> const& actionToIndexMap, 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), manager(manager), modelType(modelType), constants(constants), constantToIndexMap(), globalBooleanVariables(globalBooleanVariables), globalBooleanVariableToIndexMap(), globalIntegerVariables(globalIntegerVariables), globalIntegerVariableToIndexMap(), formulas(formulas), formulaToIndexMap(), modules(modules), moduleToIndexMap(), rewardModels(rewardModels), rewardModelToIndexMap(), initialConstruct(initialConstruct), labels(labels), actionToIndexMap(actionToIndexMap), indexToActionMap(), actions(), actionIndices(), actionIndicesToModuleIndexMap(), variableToModuleIndexMap() { + Program::Program(std::shared_ptr<storm::expressions::ExpressionManager> manager, 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::map<std::string, uint_fast64_t> const& actionToIndexMap, 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 finalModel) + : LocatedInformation(filename, lineNumber), manager(manager), + modelType(modelType), constants(constants), constantToIndexMap(), + globalBooleanVariables(globalBooleanVariables), globalBooleanVariableToIndexMap(), + globalIntegerVariables(globalIntegerVariables), globalIntegerVariableToIndexMap(), + formulas(formulas), formulaToIndexMap(), modules(modules), moduleToIndexMap(), + rewardModels(rewardModels), rewardModelToIndexMap(), initialConstruct(initialConstruct), + labels(labels), actionToIndexMap(actionToIndexMap), indexToActionMap(), actions(), + actionIndices(), actionIndicesToModuleIndexMap(), variableToModuleIndexMap() + { this->createMappings(); // Create a new initial construct if the corresponding flag was set. @@ -36,7 +45,8 @@ namespace storm { this->initialConstruct = storm::prism::InitialConstruct(newInitialExpression, this->getInitialConstruct().getFilename(), this->getInitialConstruct().getLineNumber()); } - if (checkValidity) { + if (finalModel) { + // If the model is supposed to be a CTMC, but contains probabilistic commands, we transform them to Markovian // commands and issue a warning. if (modelType == storm::prism::Program::ModelType::CTMC && storm::settings::generalSettings().isPrismCompatibilityEnabled()) { @@ -51,9 +61,8 @@ namespace storm { } STORM_LOG_WARN_COND(!hasProbabilisticCommands, "The input model is a CTMC, but uses probabilistic commands like they are used in PRISM. Consider rewriting the commands to use Markovian commands instead."); } - // Then check the validity. - this->checkValidity(); + this->checkValidity(Program::ValidityCheckLevel::VALIDINPUT); } } @@ -509,7 +518,8 @@ namespace storm { return Program(this->manager, this->getModelType(), newConstants, newBooleanVariables, newIntegerVariables, newFormulas, newModules, this->getActionNameToIndexMapping(), newRewardModels, false, newInitialConstruct, newLabels); } - void Program::checkValidity() const { + void Program::checkValidity(Program::ValidityCheckLevel lvl) const { + // Start by checking the constant declarations. std::set<storm::expressions::Variable> all; std::set<storm::expressions::Variable> allGlobals; @@ -602,40 +612,6 @@ namespace storm { std::set<storm::expressions::Variable> variablesAndConstants; std::set_union(variables.begin(), variables.end(), constants.begin(), constants.end(), std::inserter(variablesAndConstants, variablesAndConstants.begin())); - // We check for each global variable and each labeled command, whether there is at most one instance writing to that variable. - std::set<std::pair<std::string, std::string>> globalBVarsWrittenToByCommand; - std::set<std::pair<std::string, std::string>> globalIVarsWrittenToByCommand; - for(auto const& module : this->getModules()) { - std::set<std::pair<std::string, std::string>> globalBVarsWrittenToByCommandInThisModule; - std::set<std::pair<std::string, std::string>> globalIVarsWrittenToByCommandInThisModule; - for (auto const& command : module.getCommands()) { - if(!command.isLabeled()) continue; - for (auto const& update : command.getUpdates()) { - for (auto const& assignment : update.getAssignments()) { - if(this->globalBooleanVariableExists(assignment.getVariable().getName())) { - globalBVarsWrittenToByCommandInThisModule.insert({assignment.getVariable().getName(), command.getActionName()}); - } - else if(this->globalIntegerVariableExists(assignment.getVariable().getName())) { - globalIVarsWrittenToByCommandInThisModule.insert({assignment.getVariable().getName(), command.getActionName()}); - } - } - } - } - for(auto const& entry : globalIVarsWrittenToByCommandInThisModule) { - if(globalIVarsWrittenToByCommand.find(entry) != globalIVarsWrittenToByCommand.end()) { - STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << module.getFilename() << ", line " << module.getLineNumber() << ": assignment of (possibly) synchronizing command with label '" << entry.second << "' writes to global variable '" << entry.first << "'."); - } - } - for(auto const& entry : globalBVarsWrittenToByCommandInThisModule) { - if(globalBVarsWrittenToByCommand.find(entry) != globalBVarsWrittenToByCommand.end()) { - STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << module.getFilename() << ", line " << module.getLineNumber() << ": assignment of (possibly) synchronizing command with label '" << entry.second << "' writes to global variable '" << entry.first << "'."); - } - } - - globalBVarsWrittenToByCommand.insert(globalBVarsWrittenToByCommandInThisModule.begin(), globalBVarsWrittenToByCommandInThisModule.end()); - globalIVarsWrittenToByCommand.insert(globalIVarsWrittenToByCommandInThisModule.begin(), globalIVarsWrittenToByCommandInThisModule.end()); - - } // Check the commands of the modules. bool hasProbabilisticCommand = false; @@ -654,7 +630,7 @@ namespace storm { // Check the guard. std::set<storm::expressions::Variable> containedVariables = command.getGuardExpression().getVariables(); bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedVariables.begin(), containedVariables.end()); - STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": guard refers to unknown identifiers."); + STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": guard " << command.getGuardExpression() << " refers to unknown identifiers."); STORM_LOG_THROW(command.getGuardExpression().hasBooleanType(), storm::exceptions::WrongFormatException, "Error in " << command.getFilename() << ", line " << command.getLineNumber() << ": expression for guard must evaluate to type 'bool'."); // Record which types of commands were seen. @@ -762,6 +738,103 @@ namespace storm { bool isValid = std::includes(variablesAndConstants.begin(), variablesAndConstants.end(), containedVariables.begin(), containedVariables.end()); STORM_LOG_THROW(isValid, storm::exceptions::WrongFormatException, "Error in " << formula.getFilename() << ", line " << formula.getLineNumber() << ": formula expression refers to unknown identifiers."); } + + if(lvl >= Program::ValidityCheckLevel::READYFORPROCESSING) { + // We check for each global variable and each labeled command, whether there is at most one instance writing to that variable. + std::set<std::pair<std::string, std::string>> globalBVarsWrittenToByCommand; + std::set<std::pair<std::string, std::string>> globalIVarsWrittenToByCommand; + for(auto const& module : this->getModules()) { + std::set<std::pair<std::string, std::string>> globalBVarsWrittenToByCommandInThisModule; + std::set<std::pair<std::string, std::string>> globalIVarsWrittenToByCommandInThisModule; + for (auto const& command : module.getCommands()) { + if(!command.isLabeled()) continue; + for (auto const& update : command.getUpdates()) { + for (auto const& assignment : update.getAssignments()) { + if(this->globalBooleanVariableExists(assignment.getVariable().getName())) { + globalBVarsWrittenToByCommandInThisModule.insert({assignment.getVariable().getName(), command.getActionName()}); + } + else if(this->globalIntegerVariableExists(assignment.getVariable().getName())) { + globalIVarsWrittenToByCommandInThisModule.insert({assignment.getVariable().getName(), command.getActionName()}); + } + } + } + } + for(auto const& entry : globalIVarsWrittenToByCommandInThisModule) { + if(globalIVarsWrittenToByCommand.find(entry) != globalIVarsWrittenToByCommand.end()) { + STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << module.getFilename() << ", line " << module.getLineNumber() << ": assignment of (possibly) synchronizing command with label '" << entry.second << "' writes to global variable '" << entry.first << "'."); + } + } + for(auto const& entry : globalBVarsWrittenToByCommandInThisModule) { + if(globalBVarsWrittenToByCommand.find(entry) != globalBVarsWrittenToByCommand.end()) { + STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error in " << module.getFilename() << ", line " << module.getLineNumber() << ": assignment of (possibly) synchronizing command with label '" << entry.second << "' writes to global variable '" << entry.first << "'."); + } + } + } + } + } + + + Program Program::simplify() { + std::vector<Module> newModules; + std::vector<Constant> newConstants = this->getConstants(); + for (auto const& module : this->getModules()) { + std::map<storm::expressions::Variable, storm::expressions::Expression> booleanVars; + std::map<storm::expressions::Variable, storm::expressions::Expression> integerVars; + for (auto const& variable : module.getBooleanVariables()) { + booleanVars.emplace(variable.getExpressionVariable(), variable.getInitialValueExpression()); + } + for (auto const& variable : module.getIntegerVariables()) { + integerVars.emplace(variable.getExpressionVariable(), variable.getInitialValueExpression()); + } + + for (auto const& command : module.getCommands()) { + // Check all updates. + for (auto const& update : command.getUpdates()) { + // Check all assignments. + for (auto const& assignment : update.getAssignments()) { + auto bit = booleanVars.find(assignment.getVariable()); + if(bit != booleanVars.end()) { + booleanVars.erase(bit); + } else { + auto iit = integerVars.find(assignment.getVariable()); + if(iit != integerVars.end()) { + integerVars.erase(iit); + } + } + } + } + } + + std::vector<storm::prism::BooleanVariable> newBVars; + for(auto const& variable : module.getBooleanVariables()) { + if(booleanVars.count(variable.getExpressionVariable()) == 0) { + newBVars.push_back(variable); + } + } + std::vector<storm::prism::IntegerVariable> newIVars; + for(auto const& variable : module.getIntegerVariables()) { + if(integerVars.count(variable.getExpressionVariable()) == 0) { + newIVars.push_back(variable); + } + } + + newModules.emplace_back(module.getName(), newBVars, newIVars, module.getCommands()); + + for(auto const& entry : booleanVars) { + newConstants.emplace_back(entry.first, entry.second); + } + + for(auto const& entry : integerVars) { + newConstants.emplace_back(entry.first, entry.second); + } + } + + return replaceModulesAndConstantsInProgram(newModules, newConstants).substituteConstants(); + + } + + Program Program::replaceModulesAndConstantsInProgram(std::vector<Module> const& newModules, std::vector<Constant> const& newConstants) { + return Program(this->manager, modelType, newConstants, getGlobalBooleanVariables(), getGlobalIntegerVariables(), getFormulas(), newModules, getActionNameToIndexMapping(), getRewardModels(), false, getInitialConstruct(), getLabels(), "", 0, false); } storm::expressions::ExpressionManager const& Program::getManager() const { @@ -816,5 +889,7 @@ namespace storm { return stream; } + + } // namespace prism } // namepsace storm diff --git a/src/storage/prism/Program.h b/src/storage/prism/Program.h index 94bcf7353..6a124e4e0 100644 --- a/src/storage/prism/Program.h +++ b/src/storage/prism/Program.h @@ -24,6 +24,8 @@ namespace storm { */ enum class ModelType {UNDEFINED, DTMC, CTMC, MDP, CTMDP, MA}; + enum class ValidityCheckLevel : unsigned {VALIDINPUT = 0, READYFORPROCESSING = 1}; + /*! * Creates a program with the given model type, undefined constants, global variables, modules, reward * models, labels and initial states. @@ -45,9 +47,9 @@ namespace storm { * @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. + * @param finalModel If set to true, the program is checked for input-validity, as well as some post-processing. */ - Program(std::shared_ptr<storm::expressions::ExpressionManager> manager, 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::map<std::string, uint_fast64_t> const& actionToIndexMap, 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); + Program(std::shared_ptr<storm::expressions::ExpressionManager> manager, 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::map<std::string, uint_fast64_t> const& actionToIndexMap, 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 finalModel = true); // Provide default implementations for constructors and assignments. Program() = default; @@ -399,11 +401,17 @@ namespace storm { */ Program substituteConstants() const; + /** + * Entry point for static analysis for simplify. As we use the same expression manager, we recommend to not use the original program any further. + * @return A simplified, equivalent program. + */ + Program simplify(); + /*! * Checks the validity of the program. If the program is not valid, an exception is thrown with a message * that indicates the source of the problem. */ - void checkValidity() const; + void checkValidity(Program::ValidityCheckLevel lvl = Program::ValidityCheckLevel::READYFORPROCESSING) const; friend std::ostream& operator<<(std::ostream& stream, Program const& program); @@ -431,7 +439,7 @@ namespace storm { // The type of the model. ModelType modelType; - // The undefined constants of the program. + // The constants of the program. std::vector<Constant> constants; // A mapping from constant names to their corresponding indices. @@ -490,6 +498,14 @@ namespace storm { // A mapping from variable names to the modules in which they were declared. std::map<std::string, uint_fast64_t> variableToModuleIndexMap; + + /** + * Takes the current program and replaces all modules. As we reuse the expression manager, we recommend to not use the original program any further. + * @param newModules the modules which replace the old modules. + * @param newConstants the constants which replace the old constants. + * @return A program with the new modules and constants. + */ + Program replaceModulesAndConstantsInProgram(std::vector<Module> const& newModules, std::vector<Constant> const& newConstants); }; } // namespace prism diff --git a/src/utility/cli.h b/src/utility/cli.h index 3e1b820e4..8a28cb0e4 100644 --- a/src/utility/cli.h +++ b/src/utility/cli.h @@ -400,7 +400,10 @@ namespace storm { boost::optional<storm::prism::Program> program; if (settings.isSymbolicSet()) { std::string const& programFile = settings.getSymbolicModelFilename(); - program = storm::parser::PrismParser::parse(programFile); + program = storm::parser::PrismParser::parse(programFile).simplify(); + + program->checkValidity(); + std::cout << program.get() << std::endl; } // Then proceed to parsing the property (if given), since the model we are building may depend on the property. @@ -416,68 +419,68 @@ namespace storm { } formulas.push_back(formula); } - else if (settings.isPropertyFileSet()) { - std::cout << "Reading properties from " << settings.getPropertiesFilename() << std::endl; + else if (settings.isPropertyFileSet()) { + std::cout << "Reading properties from " << settings.getPropertiesFilename() << std::endl; - std::ifstream inputFileStream(settings.getPropertiesFilename(), std::ios::in); + std::ifstream inputFileStream(settings.getPropertiesFilename(), std::ios::in); - std::vector<std::string> properties; + std::vector<std::string> properties; - if (inputFileStream.good()) { - try { - while (inputFileStream.good()) { - std::string prop; - std::getline(inputFileStream, prop); - if (!prop.empty()) { - properties.push_back(prop); - } - } - } - catch (std::exception& e) { - inputFileStream.close(); - throw e; - } - inputFileStream.close(); - } else { - STORM_LOG_ERROR("Unable to read property file."); - } + if (inputFileStream.good()) { + try { + while (inputFileStream.good()) { + std::string prop; + std::getline(inputFileStream, prop); + if (!prop.empty()) { + properties.push_back(prop); + } + } + } + catch (std::exception& e) { + inputFileStream.close(); + throw e; + } + inputFileStream.close(); + } else { + STORM_LOG_ERROR("Unable to read property file."); + } - for (std::string prop : properties) { - boost::optional<std::shared_ptr<storm::logic::Formula>> formula; - try { - if (program) { - storm::parser::FormulaParser formulaParser(program.get().getManager().getSharedPointer()); - formula = formulaParser.parseFromString(prop); - } else { - storm::parser::FormulaParser formulaParser; - formula = formulaParser.parseFromString(prop); - } - formulas.push_back(formula); - } - catch (storm::exceptions::WrongFormatException &e) { - STORM_LOG_WARN("Unable to parse line as formula: " << prop); - } - } - std::cout << "Parsed " << formulas.size() << " properties from file " << settings.getPropertiesFilename() << std::endl; - } - - for (boost::optional<std::shared_ptr<storm::logic::Formula>> formula : formulas) { - if (settings.isSymbolicSet()) { + for (std::string prop : properties) { + boost::optional<std::shared_ptr<storm::logic::Formula>> formula; + try { + if (program) { + storm::parser::FormulaParser formulaParser(program.get().getManager().getSharedPointer()); + formula = formulaParser.parseFromString(prop); + } else { + storm::parser::FormulaParser formulaParser; + formula = formulaParser.parseFromString(prop); + } + formulas.push_back(formula); + } + catch (storm::exceptions::WrongFormatException &e) { + STORM_LOG_WARN("Unable to parse line as formula: " << prop); + } + } + std::cout << "Parsed " << formulas.size() << " properties from file " << settings.getPropertiesFilename() << std::endl; + } + + for (boost::optional<std::shared_ptr<storm::logic::Formula>> formula : formulas) { + if (settings.isSymbolicSet()) { #ifdef STORM_HAVE_CARL - if (settings.isParametricSet()) { - buildAndCheckSymbolicModel<storm::RationalFunction>(program.get(), formula); - } else { + if (settings.isParametricSet()) { + buildAndCheckSymbolicModel<storm::RationalFunction>(program.get(), formula); + } else { #endif - buildAndCheckSymbolicModel<double>(program.get(), formula); + buildAndCheckSymbolicModel<double>(program.get(), formula); #ifdef STORM_HAVE_CARL - } + } #endif - } else if (settings.isExplicitSet()) { - buildAndCheckExplicitModel<double>(formula); - } else { - STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model."); - } - } + } else if (settings.isExplicitSet()) { + buildAndCheckExplicitModel<double>(formula); + } else { + STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model."); + } + } } } }