From 12ac3549da0a05f4a3a1f7934f94a2a2a7c48f7b Mon Sep 17 00:00:00 2001 From: dehnert <dehnert@cs.rwth-aachen.de> Date: Mon, 5 Sep 2016 14:56:17 +0200 Subject: [PATCH] adapted relevant parts to new way of specifying initial values/restrictions Former-commit-id: a55abbe3b616900f5bd721de0eb1bcd1c5f6a5a1 [formerly 6a9d8a6a5577f7f4a524542d5c5a4b201a8c456e] Former-commit-id: 47799adaf2bd68e8e6c7356410151ab0c31b02a0 --- src/parser/JaniParser.cpp | 2 +- src/storage/jani/Automaton.cpp | 35 +++++++++++++++++++++----- src/storage/jani/Automaton.h | 23 ++++++++++------- src/storage/jani/Exporter.cpp | 30 +++++++++++----------- src/storage/jani/Model.cpp | 46 +++++++++++++++++++++------------- src/storage/jani/Model.h | 23 ++++++++++------- src/storage/jani/Variable.cpp | 4 +++ src/storage/jani/Variable.h | 5 ++++ src/storage/prism/Program.cpp | 30 +++++----------------- 9 files changed, 116 insertions(+), 82 deletions(-) diff --git a/src/parser/JaniParser.cpp b/src/parser/JaniParser.cpp index 0ebeb734d..806a26a1f 100644 --- a/src/parser/JaniParser.cpp +++ b/src/parser/JaniParser.cpp @@ -587,7 +587,7 @@ namespace storm { if(automatonStructure.count("restrict-initial") > 0) { initialValueRestriction = parseExpression(automatonStructure.at("restrict-initial"), "Initial value restriction for automaton " + name); } - automaton.setInitialStatesExpression(initialValueRestriction); + automaton.setInitialStatesRestriction(initialValueRestriction); uint64_t varDeclCount = automatonStructure.count("variables"); STORM_LOG_THROW(varDeclCount < 2, storm::exceptions::InvalidJaniException, "Automaton '" << name << "' has more than one list of variables"); std::unordered_map<std::string, std::shared_ptr<storm::jani::Variable>> localVars; diff --git a/src/storage/jani/Automaton.cpp b/src/storage/jani/Automaton.cpp index 29d0f838b..c6d8600e3 100644 --- a/src/storage/jani/Automaton.cpp +++ b/src/storage/jani/Automaton.cpp @@ -305,16 +305,39 @@ namespace storm { return edges.size(); } - bool Automaton::hasInitialStatesExpression() const { - return initialStatesExpression.isInitialized(); + bool Automaton::hasInitialStatesRestriction() const { + return initialStatesRestriction.isInitialized(); } - storm::expressions::Expression const& Automaton::getInitialStatesExpression() const { - return initialStatesExpression; + storm::expressions::Expression const& Automaton::getInitialStatesRestriction() const { + return initialStatesRestriction; } - void Automaton::setInitialStatesExpression(storm::expressions::Expression const& initialStatesExpression) { - this->initialStatesExpression = initialStatesExpression; + void Automaton::setInitialStatesRestriction(storm::expressions::Expression const& initialStatesRestriction) { + this->initialStatesRestriction = initialStatesRestriction; + } + + storm::expressions::Expression Automaton::getInitialStatesExpression() const { + storm::expressions::Expression result; + + // Add initial state restriction if there is one. + if (this->hasInitialStatesRestriction()) { + result = this->getInitialStatesRestriction(); + } + + // Add the expressions for all variables that have initial expressions. + for (auto const& variable : this->getVariables()) { + if (variable.hasInitExpression()) { + storm::expressions::Expression newInitExpression = variable.isBooleanVariable() ? storm::expressions::iff(variable.getExpressionVariable(), variable.getInitExpression()) : variable.getExpressionVariable() == variable.getInitExpression(); + if (result.isInitialized()) { + result = result && newInitExpression; + } else { + result = newInitExpression; + } + } + } + + return result; } bool Automaton::hasEdgeLabeledWithActionIndex(uint64_t actionIndex) const { diff --git a/src/storage/jani/Automaton.h b/src/storage/jani/Automaton.h index 3ea6cea4f..1a2ad61dc 100644 --- a/src/storage/jani/Automaton.h +++ b/src/storage/jani/Automaton.h @@ -232,21 +232,26 @@ namespace storm { * Retrieves the number of edges. */ uint64_t getNumberOfEdges() const; - + /*! - * Retrieves whether there is an expression defining the legal initial values of the automaton's variables. + * Retrieves whether this automaton has an initial states restriction. */ - bool hasInitialStatesExpression() const; + bool hasInitialStatesRestriction() const; /*! - * Retrieves the expression defining the legal initial values of the automaton's variables. + * Gets the expression restricting the legal initial values of the automaton's variables. */ - storm::expressions::Expression const& getInitialStatesExpression() const; + storm::expressions::Expression const& getInitialStatesRestriction() const; /*! - * Sets the expression defining the legal initial values of the automaton's variables. + * Sets the expression restricting the legal initial values of the automaton's variables. + */ + void setInitialStatesRestriction(storm::expressions::Expression const& initialStatesRestriction); + + /*! + * Retrieves the expression defining the legal initial values of the automaton's variables. */ - void setInitialStatesExpression(storm::expressions::Expression const& initialStatesExpression); + storm::expressions::Expression getInitialStatesExpression() const; /*! * Retrieves whether there is an edge labeled with the action with the given index in this automaton. @@ -287,8 +292,8 @@ namespace storm { /// The indices of the initial locations. std::set<uint64_t> initialLocationIndices; - /// The expression characterizing the legal initial values of the variables of the automaton. - storm::expressions::Expression initialStatesExpression; + /// The expression restricting the legal initial values of the variables of the automaton. + storm::expressions::Expression initialStatesRestriction; /// The set of action indices that label some action in this automaton. std::set<uint64_t> actionIndices; diff --git a/src/storage/jani/Exporter.cpp b/src/storage/jani/Exporter.cpp index 55b5d068f..51635f10a 100644 --- a/src/storage/jani/Exporter.cpp +++ b/src/storage/jani/Exporter.cpp @@ -355,7 +355,7 @@ namespace storm { appendIndent(out, indent + 1); out << "]"; clearLine(out); - if (automaton.hasInitialStatesExpression()) { + if (automaton.hasInitialStatesRestriction()) { appendIndent(out, indent + 1); appendField(out, "initial-states"); clearLine(out); @@ -413,21 +413,19 @@ namespace storm { appendVariables(out, model.getGlobalVariables(), 1); clearLine(out); - if (model.hasInitialStatesExpression()) { - appendIndent(out, 1); - appendField(out, "initial-states"); - clearLine(out); - appendIndent(out, 2); - out << "{"; - clearLine(out); - appendIndent(out, 3); - appendField(out, "exp"); - appendValue(out, expressionToString(model.getInitialStatesExpression())); - clearLine(out); - appendIndent(out, 2); - out << "}"; - clearLine(out); - } + appendIndent(out, 1); + appendField(out, "initial-states"); + clearLine(out); + appendIndent(out, 2); + out << "{"; + clearLine(out); + appendIndent(out, 3); + appendField(out, "exp"); + appendValue(out, expressionToString(model.getInitialStatesRestriction())); + clearLine(out); + appendIndent(out, 2); + out << "}"; + clearLine(out); appendAutomata(out, model, 1); clearLine(out); diff --git a/src/storage/jani/Model.cpp b/src/storage/jani/Model.cpp index 8af4dc560..a9fb3f25e 100644 --- a/src/storage/jani/Model.cpp +++ b/src/storage/jani/Model.cpp @@ -27,6 +27,9 @@ namespace storm { this->expressionManager = std::make_shared<storm::expressions::ExpressionManager>(); } + // Create an initial restriction. + initialStatesRestriction = this->expressionManager->boolean(true); + // Add a prefined action that represents the silent action. silentActionIndex = addAction(storm::jani::Action(SILENT_ACTION_NAME)); } @@ -301,25 +304,23 @@ namespace storm { // Substitute constants in all global variables. for (auto& variable : result.getGlobalVariables().getBoundedIntegerVariables()) { + variable.setInitExpression(variable.getInitExpression().substitute(constantSubstitution)); variable.setLowerBound(variable.getLowerBound().substitute(constantSubstitution)); variable.setUpperBound(variable.getUpperBound().substitute(constantSubstitution)); } // Substitute constants in initial states expression. - if (this->hasInitialStatesExpression()) { - result.setInitialStatesExpression(this->getInitialStatesExpression().substitute(constantSubstitution)); - } + result.setInitialStatesRestriction(this->getInitialStatesRestriction().substitute(constantSubstitution)); // Substitute constants in variables of automata and their edges. for (auto& automaton : result.getAutomata()) { for (auto& variable : automaton.getVariables().getBoundedIntegerVariables()) { + variable.setInitExpression(variable.getInitExpression().substitute(constantSubstitution)); variable.setLowerBound(variable.getLowerBound().substitute(constantSubstitution)); variable.setUpperBound(variable.getUpperBound().substitute(constantSubstitution)); } - if (automaton.hasInitialStatesExpression()) { - automaton.setInitialStatesExpression(automaton.getInitialStatesExpression().substitute(constantSubstitution)); - } + automaton.setInitialStatesRestriction(automaton.getInitialStatesExpression().substitute(constantSubstitution)); for (auto& edge : automaton.getEdges()) { edge.setGuard(edge.getGuard().substitute(constantSubstitution)); @@ -350,28 +351,39 @@ namespace storm { return result; } - bool Model::hasInitialStatesExpression() const { - return initialStatesExpression.isInitialized(); + void Model::setInitialStatesRestriction(storm::expressions::Expression const& initialStatesRestriction) { + this->initialStatesRestriction = initialStatesRestriction; } - + + storm::expressions::Expression const& Model::getInitialStatesRestriction() const { + return initialStatesRestriction; + } + storm::expressions::Expression Model::getInitialStatesExpression(bool includeAutomataInitialStatesExpressions) const { - STORM_LOG_THROW(globalVariables.empty() || this->hasInitialStatesExpression(), storm::exceptions::InvalidOperationException, "Cannot retrieve global initial states expression, because there is none."); - storm::expressions::Expression result = this->hasInitialStatesExpression() ? initialStatesExpression : expressionManager->boolean(true); + // Start with the restriction of variables. + storm::expressions::Expression result = initialStatesRestriction; + + // Then add initial values for those variables that have one. + for (auto const& variable : globalVariables) { + if (variable.hasInitExpression()) { + result = result && (variable.isBooleanVariable() ? storm::expressions::iff(variable.getExpressionVariable(), variable.getInitExpression()) : variable.getExpressionVariable() == variable.getInitExpression()); + } + } + + // If we are to include the expressions for the automata, do so now. if (includeAutomataInitialStatesExpressions) { for (auto const& automaton : automata) { - STORM_LOG_THROW(automaton.getVariables().empty() || automaton.hasInitialStatesExpression(), storm::exceptions::InvalidOperationException, "Cannot retrieve initial states expression from automaton '" << automaton.getName() << "', because there is none."); if (!automaton.getVariables().empty()) { - result = result && automaton.getInitialStatesExpression(); + storm::expressions::Expression automatonInitialStatesExpression = automaton.getInitialStatesExpression(); + if (automatonInitialStatesExpression.isInitialized() && !automatonInitialStatesExpression.isTrue()) { + result = result && automatonInitialStatesExpression; + } } } } return result; } - void Model::setInitialStatesExpression(storm::expressions::Expression const& initialStatesExpression) { - this->initialStatesExpression = initialStatesExpression; - } - bool Model::isDeterministicModel() const { return this->getModelType() == ModelType::DTMC || this->getModelType() == ModelType::CTMC; } diff --git a/src/storage/jani/Model.h b/src/storage/jani/Model.h index 95163fda9..0379cd5dd 100644 --- a/src/storage/jani/Model.h +++ b/src/storage/jani/Model.h @@ -236,9 +236,19 @@ namespace storm { std::map<storm::expressions::Variable, storm::expressions::Expression> getConstantsSubstitution() const; /*! - * Retrieves whether there is an expression defining the legal initial values of the global variables. + * Retrieves whether there is an expression restricting the legal initial values of the global variables. */ - bool hasInitialStatesExpression() const; + bool hasInitialStatesRestriction() const; + + /*! + * Sets the expression restricting the legal initial values of the global variables. + */ + void setInitialStatesRestriction(storm::expressions::Expression const& initialStatesRestriction); + + /*! + * Gets the expression restricting the legal initial values of the global variables. + */ + storm::expressions::Expression const& getInitialStatesRestriction() const; /*! * Retrieves the expression defining the legal initial values of the variables. @@ -248,11 +258,6 @@ namespace storm { */ storm::expressions::Expression getInitialStatesExpression(bool includeAutomataInitialStatesExpressions = false) const; - /*! - * Sets the expression defining the legal initial values of the global variables. - */ - void setInitialStatesExpression(storm::expressions::Expression const& initialStatesExpression); - /*! * Determines whether this model is a deterministic one in the sense that each state only has one choice. */ @@ -329,8 +334,8 @@ namespace storm { /// An expression describing how the system is composed of the automata. std::shared_ptr<Composition> composition; - // The expression characterizing the legal initial values of the global variables. - storm::expressions::Expression initialStatesExpression; + // The expression restricting the legal initial values of the global variables. + storm::expressions::Expression initialStatesRestriction; }; } } diff --git a/src/storage/jani/Variable.cpp b/src/storage/jani/Variable.cpp index ad7a1de51..57a9289a4 100644 --- a/src/storage/jani/Variable.cpp +++ b/src/storage/jani/Variable.cpp @@ -48,6 +48,10 @@ namespace storm { return this->init.get(); } + void Variable::setInitExpression(storm::expressions::Expression const& initialExpression) { + this->init = initialExpression; + } + BooleanVariable& Variable::asBooleanVariable() { return dynamic_cast<BooleanVariable&>(*this); } diff --git a/src/storage/jani/Variable.h b/src/storage/jani/Variable.h index d5ba1f20b..820014b03 100644 --- a/src/storage/jani/Variable.h +++ b/src/storage/jani/Variable.h @@ -49,6 +49,11 @@ namespace storm { */ storm::expressions::Expression const& getInitExpression() const; + /*! + * Sets the initial expression for this variable. + */ + void setInitExpression(storm::expressions::Expression const& initialExpression); + // Methods to determine the type of the variable. virtual bool isBooleanVariable() const; virtual bool isBoundedIntegerVariable() const; diff --git a/src/storage/prism/Program.cpp b/src/storage/prism/Program.cpp index f946fbb98..3562747e7 100644 --- a/src/storage/prism/Program.cpp +++ b/src/storage/prism/Program.cpp @@ -1527,7 +1527,6 @@ namespace storm { default: modelType = storm::jani::ModelType::UNDEFINED; } storm::jani::Model janiModel("jani_from_prism", modelType, 1, manager); - storm::expressions::Expression globalInitialStatesExpression; // Add all constants of the PRISM program to the JANI model. for (auto const& constant : constants) { @@ -1540,16 +1539,12 @@ namespace storm { // Add all global variables of the PRISM program to the JANI model. for (auto const& variable : globalIntegerVariables) { - storm::jani::BoundedIntegerVariable const& newVariable = janiModel.addBoundedIntegerVariable(storm::jani::BoundedIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getLowerBoundExpression(), variable.getUpperBoundExpression())); + storm::jani::BoundedIntegerVariable const& newVariable = janiModel.addBoundedIntegerVariable(storm::jani::BoundedIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), variable.getLowerBoundExpression(), variable.getUpperBoundExpression())); variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable); - storm::expressions::Expression variableInitialExpression = variable.getExpressionVariable() == variable.getInitialValueExpression(); - globalInitialStatesExpression = globalInitialStatesExpression.isInitialized() ? globalInitialStatesExpression && variableInitialExpression : variableInitialExpression; } for (auto const& variable : globalBooleanVariables) { - storm::jani::BooleanVariable const& newVariable = janiModel.addBooleanVariable(storm::jani::BooleanVariable(variable.getName(), variable.getExpressionVariable())); + storm::jani::BooleanVariable const& newVariable = janiModel.addBooleanVariable(storm::jani::BooleanVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression())); variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable); - storm::expressions::Expression variableInitialExpression = storm::expressions::iff(variable.getExpressionVariable(), variable.getInitialValueExpression()); - globalInitialStatesExpression = globalInitialStatesExpression.isInitialized() ? globalInitialStatesExpression && variableInitialExpression : variableInitialExpression; } // Add all actions of the PRISM program to the JANI model. @@ -1589,45 +1584,34 @@ namespace storm { // previously built mapping to make variables global that are read by more than one module. for (auto const& module : modules) { storm::jani::Automaton automaton(module.getName()); - storm::expressions::Expression initialStatesExpression; for (auto const& variable : module.getIntegerVariables()) { - storm::jani::BoundedIntegerVariable newIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getLowerBoundExpression(), variable.getUpperBoundExpression()); + storm::jani::BoundedIntegerVariable newIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), variable.getLowerBoundExpression(), variable.getUpperBoundExpression()); std::set<uint_fast64_t> const& accessingModuleIndices = variablesToAccessingModuleIndices[variable.getExpressionVariable()]; // If there is exactly one module reading and writing the variable, we can make the variable local to this module. if (!allVariablesGlobal && accessingModuleIndices.size() == 1) { storm::jani::BoundedIntegerVariable const& newVariable = automaton.addBoundedIntegerVariable(newIntegerVariable); variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable); - storm::expressions::Expression variableInitialExpression = variable.getExpressionVariable() == variable.getInitialValueExpression(); - initialStatesExpression = initialStatesExpression.isInitialized() ? initialStatesExpression && variableInitialExpression : variableInitialExpression; } else if (!accessingModuleIndices.empty()) { // Otherwise, we need to make it global. storm::jani::BoundedIntegerVariable const& newVariable = janiModel.addBoundedIntegerVariable(newIntegerVariable); variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable); - storm::expressions::Expression variableInitialExpression = variable.getExpressionVariable() == variable.getInitialValueExpression(); - globalInitialStatesExpression = globalInitialStatesExpression.isInitialized() ? globalInitialStatesExpression && variableInitialExpression : variableInitialExpression; } } for (auto const& variable : module.getBooleanVariables()) { - storm::jani::BooleanVariable newBooleanVariable(variable.getName(), variable.getExpressionVariable()); + storm::jani::BooleanVariable newBooleanVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression()); std::set<uint_fast64_t> const& accessingModuleIndices = variablesToAccessingModuleIndices[variable.getExpressionVariable()]; // If there is exactly one module reading and writing the variable, we can make the variable local to this module. if (!allVariablesGlobal && accessingModuleIndices.size() == 1) { storm::jani::BooleanVariable const& newVariable = automaton.addBooleanVariable(newBooleanVariable); variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable); - storm::expressions::Expression variableInitialExpression = storm::expressions::iff(variable.getExpressionVariable(), variable.getInitialValueExpression()); - initialStatesExpression = initialStatesExpression.isInitialized() ? initialStatesExpression && variableInitialExpression : variableInitialExpression; } else if (!accessingModuleIndices.empty()) { // Otherwise, we need to make it global. storm::jani::BooleanVariable const& newVariable = janiModel.addBooleanVariable(newBooleanVariable); variableToVariableMap.emplace(variable.getExpressionVariable(), newVariable); - storm::expressions::Expression variableInitialExpression = storm::expressions::iff(variable.getExpressionVariable(), variable.getInitialValueExpression()); - globalInitialStatesExpression = globalInitialStatesExpression.isInitialized() ? globalInitialStatesExpression && variableInitialExpression : variableInitialExpression; } } - - // Set the proper expression characterizing the initial values of the automaton's variables. - automaton.setInitialStatesExpression(initialStatesExpression); + automaton.setInitialStatesRestriction(manager->boolean(true)); // Create a single location that will have all the edges. uint64_t onlyLocation = automaton.addLocation(storm::jani::Location("l")); @@ -1663,9 +1647,7 @@ namespace storm { janiModel.addAutomaton(automaton); } - - // Set the proper expression characterizing the initial values of the global variables. - janiModel.setInitialStatesExpression(globalInitialStatesExpression); + janiModel.setInitialStatesRestriction(manager->boolean(true)); // Set the standard system composition. This is possible, because we reject non-standard compositions anyway. if (this->specifiesSystemComposition()) {