18 "Model has no automaton with name " << automatonName <<
". ");
20 storm::exceptions::IllegalArgumentException,
"Automaton " << automatonName <<
" has no variable with name " << variableName <<
". ");
22 AutomatonAndIndices newAutomaton = transformAutomaton(original.
getAutomaton(automatonName), variableName,
true);
24 return {newModel, newAutomaton.newIndices};
27JaniLocationExpander::AutomatonAndIndices JaniLocationExpander::transformAutomaton(
Automaton const &automaton, std::string
const &variableName,
28 bool useTransientVariables) {
30 NewIndices newIndices;
31 std::map<Variable const *, std::reference_wrapper<Variable const>> variableRemapping;
33 for (
auto const &localVariable : automaton.getVariables()) {
34 newAutomaton.addVariable(localVariable);
36 std::reference_wrapper<Variable const> ref_w = std::cref(newAutomaton.getVariables().getVariable(localVariable.getName()));
38 variableRemapping.insert(std::pair<
Variable const *, std::reference_wrapper<Variable const>>(&localVariable, ref_w));
41 bool isGlobalVariable = !automaton.
hasVariable(variableName);
42 VariableSet &containingSet = isGlobalVariable ? newModel.
getGlobalVariables() : newAutomaton.getVariables();
44 const bool substituteTranscendentalNumbers =
false;
45 auto &var = containingSet.
getVariable(variableName);
46 bool isBoundedInteger = var.
getType().
isBoundedType() && var.getType().asBoundedType().isIntegerType();
47 bool isBool = var.getType().isBasicType() && var.getType().asBasicType().isBooleanType();
49 STORM_LOG_THROW(isBoundedInteger || isBool, storm::exceptions::InvalidOperationException,
50 "Variable to be eliminated has to be an bounded integer or boolean variable.");
51 STORM_LOG_THROW(var.hasInitExpression(), storm::exceptions::InvalidOperationException,
"Variable to be eliminated has to have an initexpression.");
52 STORM_LOG_THROW(!var.isTransient(), storm::exceptions::InvalidOperationException,
"Cannot eliminate transient variable");
60 uint32_t initialValueIndex;
62 if (isBoundedInteger) {
63 auto biVariable = containingSet.getVariable(variableName).
getType().asBoundedType();
65 int64_t variableUpperBound = biVariable.getUpperBound().evaluateAsInt();
66 int64_t variableLowerBound = biVariable.getLowerBound().evaluateAsInt();
67 int64_t initialVariableValue = containingSet.getVariable(variableName).getInitExpression().evaluateAsInt();
68 for (int64_t i = variableLowerBound; i <= variableUpperBound; i++) {
71 initialValueIndex = initialVariableValue - variableLowerBound;
73 containingSet.eraseVariable(var.getExpressionVariable());
75 biVariable.getUpperBound());
76 containingSet.addVariable(*newVar);
79 auto boolVariable = containingSet.getVariable(variableName).getType().asBasicType();
82 bool initialValue = containingSet.getVariable(variableName).getInitExpression().evaluateAsBool();
84 initialValueIndex = 1;
86 initialValueIndex = 0;
89 containingSet.eraseVariable(containingSet.getVariable(variableName).getExpressionVariable());
91 containingSet.addVariable(*newVar);
94 const Variable &newVariablePointer = containingSet.getVariable(variableName);
97 std::map<storm::expressions::Variable, storm::expressions::Expression> substitutionMap;
99 for (
auto const &loc : automaton.getLocations()) {
102 if (excludedLocations.count(origIndex) > 0) {
103 STORM_LOG_THROW(loc.getAssignments().empty(), storm::exceptions::IllegalArgumentException,
104 "Locations with assignments cannot be excluded during expansion");
106 "Locations with outgoing edges cannot be excluded during expansion");
108 Location newLoc(loc.getName(), OrderedAssignments());
109 uint64_t newLocationIndex = newAutomaton.addLocation(newLoc);
110 newIndices.excludedLocationsToNewIndices[origIndex] = newLocationIndex;
111 for (uint64_t i = 0;
i < newIndices.variableDomain.size();
i++) {
112 newIndices.locationVariableValueMap[origIndex][
i] = newLocationIndex;
115 for (uint64_t i = 0;
i < newIndices.variableDomain.size();
i++) {
116 std::string newLocationName = loc.getName() +
"_" + variableName +
"_" + newIndices.variableDomain[
i].toString();
117 substitutionMap[eliminatedExpressionVariable] = newIndices.variableDomain[
i];
119 OrderedAssignments newAssignments = loc.getAssignments().clone();
120 newAssignments.substitute(substitutionMap, substituteTranscendentalNumbers);
122 Location newLoc(newLocationName, newAssignments);
124 if (useTransientVariables)
125 newLoc.addTransientAssignment(Assignment(newVariablePointer, newIndices.variableDomain[i], 0));
127 uint64_t newLocationIndex = newAutomaton.addLocation(newLoc);
128 newIndices.locationVariableValueMap[origIndex][
i] = newLocationIndex;
133 for (uint64_t
const &initialLoc : automaton.getInitialLocationIndices()) {
134 newAutomaton.addInitialLocation(newIndices.locationVariableValueMap[initialLoc][initialValueIndex]);
137 for (
auto const &edge : automaton.getEdges()) {
138 for (
auto const &newValueAndLocation : newIndices.locationVariableValueMap[edge.getSourceLocationIndex()]) {
139 int64_t currentValueIndex = newValueAndLocation.first;
141 substitutionMap[eliminatedExpressionVariable] = newIndices.variableDomain[currentValueIndex];
143 uint64_t newSourceIndex = newValueAndLocation.second;
148 bool isEdgeInvalid =
false;
150 std::shared_ptr<storm::jani::TemplateEdge> templateEdge = std::make_shared<storm::jani::TemplateEdge>(newGuard);
152 STORM_LOG_THROW(edge.getAssignments().empty(), storm::exceptions::NotImplementedException,
"Support for edge-assignments is not implemented");
154 std::vector<std::pair<uint64_t, storm::expressions::Expression>> destinationLocationsAndProbabilities;
155 for (
auto const &destination : edge.getDestinations()) {
156 OrderedAssignments oa(destination.getOrderedAssignments().clone());
157 oa.substitute(substitutionMap, substituteTranscendentalNumbers);
159 int64_t newValueIndex = currentValueIndex;
160 for (
auto const &assignment : oa) {
161 if (assignment.getVariable().getExpressionVariable().getIndex() == var.getExpressionVariable().getIndex()) {
162 if (isBoundedInteger) {
164 newValueIndex = assignment.getAssignedExpression().evaluateAsInt() - newIndices.variableDomain[0].evaluateAsInt();
166 if (assignment.getAssignedExpression().evaluateAsBool()) {
172 oa.remove(assignment);
177 if (newValueIndex < 0 || newValueIndex >=
static_cast<int64_t
>(newIndices.variableDomain.size())) {
179 "Found edge that would lead to out-of-range location during unfolding. This edge will not be added to the unfolded model. It is "
180 "possible that the edge guard is unsatisfiable, in which case this message can be ignored.");
181 isEdgeInvalid =
true;
186 if (!useTransientVariables)
187 STORM_LOG_THROW(
true, storm::exceptions::NotImplementedException,
"Unfolding without transient variables is not implemented");
190 TemplateEdgeDestination ted(oa);
191 templateEdge->addDestination(ted);
192 destinationLocationsAndProbabilities.emplace_back(
193 newIndices.locationVariableValueMap[destination.getLocationIndex()][newValueIndex],
197 if (!isEdgeInvalid) {
198 templateEdge->finalize(newModel);
201 edge.getRate(), substitutionMap, substituteTranscendentalNumbers))
203 templateEdge, destinationLocationsAndProbabilities));
204 newAutomaton.registerTemplateEdge(templateEdge);
209 newAutomaton.changeAssignmentVariables(variableRemapping);
211 return {newAutomaton, newIndices};
215 excludedLocations.insert(index);
Expression simplify() const
Simplifies the expression according to some basic rules.
bool evaluateAsBool(Valuation const *valuation=nullptr) const
Evaluates the expression under the valuation of variables given by the valuation and returns the resu...
bool containsVariables() const
Retrieves whether the expression contains a variable.
Expression integer(int_fast64_t value) const
Creates an expression that characterizes the given integer literal.
Expression boolean(bool value) const
Creates an expression that characterizes the given boolean literal.
Type const & getType() const
Retrieves the type of the variable.
storm::expressions::Expression const & getInitialStatesRestriction() const
Gets the expression restricting the legal initial values of the automaton's variables.
bool hasVariable(std::string const &name) const
storm::expressions::Variable const & getLocationExpressionVariable() const
Retrieves the expression variable that represents the location of this automaton.
Edges getEdgesFromLocation(std::string const &name)
Retrieves the edges of the location with the given name.
std::string const & getName() const
Retrieves the name of the automaton.
uint64_t getLocationIndex(std::string const &name) const
JaniLocationExpander(Model const &original)
void excludeLocation(uint64_t index)
ReturnType transform(std::string const &automatonName, std::string const &variableName)
virtual bool isBoundedType() const
VariableSet & getGlobalVariables()
Retrieves the variables of this automaton.
storm::expressions::ExpressionManager & getExpressionManager() const
Retrieves the manager responsible for the expressions in the JANI model.
void replaceAutomaton(uint64_t index, Automaton const &newAutomaton)
Replaces the automaton at index with a new automaton.
bool hasGlobalVariable(std::string const &name) const
Retrieves whether this model has a global variable with the given name.
bool hasAutomaton(std::string const &name) const
Rerieves whether there exists an automaton with the given name.
Automaton & getAutomaton(std::string const &name)
Retrieves the automaton with the given name.
uint64_t getAutomatonIndex(std::string const &name) const
Retrieves the index of the given automaton.
static std::shared_ptr< Variable > makeBooleanVariable(std::string const &name, storm::expressions::Variable const &variable, boost::optional< storm::expressions::Expression > const &initValue, bool transient)
static std::shared_ptr< Variable > makeBoundedIntegerVariable(std::string const &name, storm::expressions::Variable const &variable, boost::optional< storm::expressions::Expression > const &initValue, bool transient, boost::optional< storm::expressions::Expression > const &lowerBound, boost::optional< storm::expressions::Expression > const &upperBound)
Variable const & getVariable(std::string const &name) const
Retrieves the variable with the given name.
bool empty() const
Determines whether this set of edges is empty.
#define STORM_LOG_WARN(message)
#define STORM_LOG_THROW(cond, exception, message)
storm::expressions::Expression substituteJaniExpression(storm::expressions::Expression const &expression, std::map< storm::expressions::Variable, storm::expressions::Expression > const &identifierToExpressionMap, bool const substituteTranscendentalNumbers)