20 : name(name), locationExpressionVariable(locationExpressionVariable) {
22 locationToStartingIndex.push_back(0);
26 std::string
const& variablePrefix) {
28 return manager.declareVariable(variablePrefix + var.
getName(), var.
getType());
33 result.name = nameOfClone;
34 result.locationExpressionVariable =
cloneVariable(manager, result.locationExpressionVariable, variablePrefix);
36 std::map<storm::expressions::Variable, storm::expressions::Expression> oldToNewVarMap;
37 for (
auto const& v : allVars) {
42 const bool substituteTranscendentalNumbers =
false;
43 result.
substitute(oldToNewVarMap, substituteTranscendentalNumbers);
68 std::set<storm::expressions::Variable> result;
70 result.insert(variable.getExpressionVariable());
80 auto insertionRes = functionDefinitions.emplace(functionDefinition.
getName(), functionDefinition);
81 STORM_LOG_THROW(insertionRes.second, storm::exceptions::InvalidArgumentException,
82 " a function with the name " << functionDefinition.
getName() <<
" already exists in this automaton (" << this->getName() <<
")");
83 return insertionRes.first->second;
87 return functionDefinitions;
91 return functionDefinitions;
95 return locationToIndex.find(name) != locationToIndex.end();
107 return locations[index];
111 return locations[index];
116 "Cannot add location with name '" << location.
getName() <<
"', because a location with this name already exists.");
117 locationToIndex.emplace(location.
getName(), locations.size());
118 locations.push_back(location);
119 locationToStartingIndex.push_back(edges.
size());
120 return locations.size() - 1;
125 return locationToIndex.at(name);
129 auto it = locationToIndex.find(name);
130 STORM_LOG_THROW(it != locationToIndex.end(), storm::exceptions::InvalidArgumentException,
131 "Cannot make unknown location '" << name <<
"' the initial location.");
136 STORM_LOG_THROW(index < locations.size(), storm::exceptions::InvalidArgumentException,
137 "Cannot make location with index " << index <<
" initial: out of bounds.");
138 initialLocationIndices.insert(index);
142 return initialLocationIndices;
146 std::map<uint64_t, std::string> mapping;
148 for (
auto const& loc : locations) {
149 mapping[i] = loc.getName();
156 return locationExpressionVariable;
164 auto it = locationToIndex.find(name);
165 STORM_LOG_THROW(it != locationToIndex.end(), storm::exceptions::InvalidArgumentException,
"Cannot retrieve edges from unknown location '" << name <<
".");
170 auto it = edges.
begin();
171 std::advance(it, locationToStartingIndex[index]);
172 auto ite = edges.
begin();
173 std::advance(ite, locationToStartingIndex[index + 1]);
174 return Edges(it, ite);
178 auto it = locationToIndex.find(name);
179 STORM_LOG_THROW(it != locationToIndex.end(), storm::exceptions::InvalidArgumentException,
"Cannot retrieve edges from unknown location '" << name <<
".");
184 auto it = edges.
begin();
185 std::advance(it, locationToStartingIndex[index]);
186 auto ite = edges.
begin();
187 std::advance(ite, locationToStartingIndex[index + 1]);
192 typedef std::vector<Edge>::iterator ForwardIt;
195 auto first = edges.
begin();
196 std::advance(first, locationToStartingIndex[locationIndex]);
197 auto last = edges.
begin();
198 std::advance(last, locationToStartingIndex[locationIndex + 1]);
199 typename std::iterator_traits<ForwardIt>::difference_type count, step;
200 count = std::distance(first, last);
206 std::advance(it1, step);
207 if (it1->getActionIndex() < actionIndex) {
217 if (it1 != last && it1->getActionIndex() > actionIndex) {
218 return Edges(last, last);
222 count = std::distance(it1, last);
228 std::advance(it2, step);
229 if (!(actionIndex < it2->getActionIndex())) {
237 return Edges(it1, it2);
241 typedef std::vector<Edge>::const_iterator ForwardIt;
244 auto first = edges.
begin();
245 std::advance(first, locationToStartingIndex[locationIndex]);
246 auto last = edges.
begin();
247 std::advance(last, locationToStartingIndex[locationIndex + 1]);
248 typename std::iterator_traits<ForwardIt>::difference_type count, step;
249 count = std::distance(first, last);
255 std::advance(it1, step);
256 if (it1->getActionIndex() < actionIndex) {
266 if (it1 != last && it1->getActionIndex() > actionIndex) {
271 count = std::distance(it1, last);
277 std::advance(it2, step);
278 if (!(actionIndex < it2->getActionIndex())) {
307 for (uint64_t locationIndex = edge.
getSourceLocationIndex() + 1; locationIndex < locationToStartingIndex.size(); ++locationIndex) {
308 ++locationToStartingIndex[locationIndex];
325 return locations.size();
353 if (variable.hasInitExpression() && !variable.isTransient()) {
362 return initialStatesRestriction;
366 this->initialStatesRestriction = initialStatesRestriction;
379 if (variable.isTransient()) {
383 if (variable.hasInitExpression()) {
385 if (variable.getType().isBasicType() && variable.getType().asBasicType().isBooleanType()) {
388 newInitExpression = variable.getExpressionVariable() == variable.getInitExpression();
391 result = result && newInitExpression;
393 result = newInitExpression;
408 if (variable.isTransient()) {
412 result &= variable.hasInitExpression();
423 return actionIndices.find(actionIndex) != actionIndices.end();
427 std::vector<storm::expressions::Expression> result;
429 result.push_back(variable.getRangeExpression());
434void Automaton::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression>
const& substitution,
435 bool const substituteTranscendentalNumbers) {
437 functionDefinition.second.substitute(substitution, substituteTranscendentalNumbers);
443 location.substitute(substitution, substituteTranscendentalNumbers);
450 edges.
substitute(substitution, substituteTranscendentalNumbers);
457 for (
auto& location : locations) {
458 location.changeAssignmentVariables(remapping);
477 if (this->
getVariables().containsVariablesInBoundExpressionsOrInitialValues(variables)) {
482 for (
auto const& edge : edges) {
483 if (edge.usesVariablesInNonTransientAssignments(variables)) {
496 std::set<std::shared_ptr<storm::jani::TemplateEdge>> encounteredTemplateEdges;
498 for (uint64_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex) {
499 auto& location = locations[locationIndex];
503 bool createNewLocation =
true;
504 for (
auto& edge : edges) {
505 STORM_LOG_THROW(encounteredTemplateEdges.find(edge.getTemplateEdge()) == encounteredTemplateEdges.end(), storm::exceptions::NotSupportedException,
506 "Pushing location assignments to edges is only supported for automata with unique template edges.");
508 auto& templateEdge = edge.getTemplateEdge();
509 encounteredTemplateEdges.insert(templateEdge);
511 for (
auto const& assignment : location.getAssignments().getTransientAssignments()) {
512 auto const& var = assignment.getVariable();
513 if (var.isTransient() && var.getType().isBasicType() && var.getType().asBasicType().isRealType()) {
514 templateEdge->addTransientAssignment(assignment,
true);
515 }
else if (createNewLocation) {
520 if (createNewLocation) {
521 createNewLocation =
false;
525 location = std::move(newLocation);
530 for (
auto const& edge : this->
getEdges()) {
531 if (edge.hasTransientEdgeDestinationAssignments()) {
543 assert(locationToStartingIndex.size() == locations.size() + 1);
544 for (uint64_t i = 0; i < locations.size(); i++) {
545 assert(locationToStartingIndex[i] <= locationToStartingIndex[i + 1]);
558 result &= location.isLinear();
570 actionIndices.clear();
571 for (
auto& e : locationToStartingIndex) {
575 for (
auto const& index : edgeIndices) {
576 this->
addEdge(oldEdges[index]);
581 outStream <<
"\tsubgraph " << name <<
" {\n";
584 uint64_t locIndex = 0;
585 for (
auto const& loc : locations) {
586 outStream <<
"\t" << name <<
"_s" << locIndex <<
"[ label=\"" << loc.getName() <<
"\"];\n";
590 uint64_t edgeIndex = 0;
591 for (
auto const& edge : edges) {
592 outStream <<
"\t" << name <<
"_e" << edgeIndex <<
"[ label=\"\" , shape=circle, width=.2, style=filled, fillcolor=\"black\"];\n";
601 for (
auto const& edge : edges) {
602 outStream <<
"\t" << name <<
"_s" << edge.getSourceLocationIndex() <<
" -> " << name <<
"_e" << edgeIndex <<
" [label=\""
603 << actionNames.at(edge.getActionIndex()) <<
"\"];\n";
604 for (
auto const& edgeDest : edge.getDestinations()) {
605 outStream <<
"\t" << name <<
"_e" << edgeIndex <<
" -> " << name <<
"_s" << edgeDest.getLocationIndex() <<
";\n";
610 outStream <<
"\t}\n";
bool evaluateAsBool(Valuation const *valuation=nullptr) const
Evaluates the expression under the valuation of variables given by the valuation and returns the resu...
bool isInitialized() const
Checks whether the object encapsulates a base-expression.
This class is responsible for managing a set of typed variables and all expressions using these varia...
ExpressionManager const & getManager() const
Retrieves the manager responsible for this variable.
Type const & getType() const
Retrieves the type of the variable.
storm::expressions::Expression getExpression() const
Retrieves an expression that represents the variable.
std::string const & getName() const
Retrieves the name of the variable.
detail::ConstEdges ConstEdges
VariableSet & getVariables()
Retrieves the variables of this automaton.
Automaton clone(storm::expressions::ExpressionManager &manager, std::string const &nameOfClone, std::string const &variablePrefix) const
bool usesAssignmentLevels(bool onlyTransient=false) const
Retrieves whether the automaton uses an assignment level other than zero.
std::set< storm::expressions::Variable > getAllExpressionVariables() const
Retrieves all expression variables used by this automaton.
void addEdge(Edge const &edge)
Adds an edge to the automaton.
storm::expressions::Expression const & getInitialStatesRestriction() const
Gets the expression restricting the legal initial values of the automaton's variables.
bool hasLocation(std::string const &name) const
Retrieves whether the automaton has a location with the given name.
void registerTemplateEdge(std::shared_ptr< TemplateEdge > const &)
Adds the template edge to the list of edges.
void finalize(Model const &containingModel)
Finalizes the building of this automaton.
bool hasVariable(std::string const &name) const
Automaton(std::string const &name, storm::expressions::Variable const &locationExpressionVariable)
Creates an empty automaton.
storm::expressions::Expression getInitialStatesExpression() const
Retrieves the expression defining the legal initial values of the automaton's variables.
storm::expressions::Variable const & getLocationExpressionVariable() const
Retrieves the expression variable that represents the location of this automaton.
Location const & getLocation(uint64_t index) const
Retrieves the location with the given index.
std::set< uint64_t > const & getInitialLocationIndices() const
Retrieves the indices of the initial locations.
std::vector< storm::expressions::Expression > getAllRangeExpressions() const
Retrieves a list of expressions that characterize the legal values of the variables in this automaton...
bool isLinear() const
Checks the automaton for linearity.
void setInitialStatesRestriction(storm::expressions::Expression const &initialStatesRestriction)
Sets the expression restricting the legal initial values of the automaton's variables.
Variable const & addVariable(Variable const &variable)
Adds the given variable to this automaton.
bool hasTrivialInitialStatesExpression() const
Retrieves whether the initial states expression is trivial in the sense that the automaton has no ini...
FunctionDefinition const & addFunctionDefinition(FunctionDefinition const &functionDefinition)
Adds the given function definition.
void addInitialLocation(std::string const &name)
Adds the location with the given name to the initial locations.
uint64_t getNumberOfEdges() const
Retrieves the number of edges.
bool hasRestrictedInitialStates() const
Retrieves whether the initial restriction is set and unequal to true.
uint64_t addLocation(Location const &location)
Adds the given location to the automaton.
void changeAssignmentVariables(std::map< Variable const *, std::reference_wrapper< Variable const > > const &remapping)
Changes all variables in assignments based on the given mapping.
void substitute(std::map< storm::expressions::Variable, storm::expressions::Expression > const &substitution, bool const substituteTranscendentalNumbers)
Substitutes all variables in all expressions according to the given substitution.
bool containsVariablesOnlyInProbabilitiesOrTransientAssignments(std::set< storm::expressions::Variable > const &variables) const
Checks whether the provided variables only appear in the probability expressions or the expressions b...
std::vector< Location > const & getLocations() const
Retrieves the locations of the automaton.
Edge const & getEdge(uint64_t index) const
Retrieves the edge with the given index in this automaton.
uint64_t getNumberOfLocations() const
Retrieves the number of locations.
Edges getEdgesFromLocation(std::string const &name)
Retrieves the edges of the location with the given name.
bool hasNonTrivialInitialStates() const
Retrieves whether this automaton has non-trivial initial states.
bool hasEdgeLabeledWithActionIndex(uint64_t actionIndex) const
Retrieves whether there is an edge labeled with the action with the given index in this automaton.
bool hasTransientVariable() const
Retrieves whether this automaton has a transient variable.
bool hasInitialStatesRestriction() const
Retrieves whether this automaton has an initial states restriction.
void pushTransientRealLocationAssignmentsToEdges()
Pushes the assignments to real-valued transient variables to the edges.
void writeDotToStream(std::ostream &outStream, std::vector< std::string > const &actionNames) const
std::unordered_map< std::string, FunctionDefinition > const & getFunctionDefinitions() const
Retrieves all function definitions of this automaton.
std::string const & getName() const
Retrieves the name of the automaton.
bool hasTransientEdgeDestinationAssignments() const
Retrieves whether there is any transient edge destination assignment in the automaton.
std::set< uint64_t > getActionIndices() const
Retrieves the set of action indices that are labels of edges of this automaton.
void liftTransientEdgeDestinationAssignments(int64_t maxLevel=0)
Lifts the common edge destination assignments to edge assignments.
std::vector< Edge > & getEdges()
Retrieves the edges of the automaton.
void pushEdgeAssignmentsToDestinations()
Pushes the edge assignments to the corresponding destinations.
uint64_t getLocationIndex(std::string const &name) const
EdgeContainer const & getEdgeContainer() const
Retrieves the container of all edges of this automaton.
void restrictToEdges(storm::storage::FlatSet< uint_fast64_t > const &edgeIndices)
Restricts the automaton to the edges given by the indices.
std::map< uint64_t, std::string > buildIdToLocationNameMap() const
Builds a map from ID to Location Name.
void clearConcreteEdges()
void changeAssignmentVariables(std::map< Variable const *, std::reference_wrapper< Variable const > > const &remapping)
void pushAssignmentsToDestinations()
std::set< uint64_t > getActionIndices() const
void insertEdge(Edge const &e, uint64_t locStart, uint64_t locEnd)
Insert an edge, then sort the range between locstart and locend according to the action index.
void finalize(Model const &containingModel)
std::vector< Edge > const & getConcreteEdges() const
void insertTemplateEdge(std::shared_ptr< TemplateEdge > const &te)
bool usesAssignmentLevels(bool onlyTransient=false) const
void liftTransientDestinationAssignments(int64_t maxLevel=0)
void substitute(std::map< storm::expressions::Variable, storm::expressions::Expression > const &substitution, bool const substituteTranscendentalNumbers)
uint64_t getActionIndex() const
Retrieves the id of the action with which this edge is labeled.
uint64_t getSourceLocationIndex() const
Retrieves the index of the source location.
std::string const & getName() const
Retrieves the name of the function.
void addTransientAssignment(storm::jani::Assignment const &assignment)
Adds the given transient assignment to this location.
std::string const & getName() const
Retrieves the name of the location.
detail::Variables< Variable > getBoundedIntegerVariables()
Retrieves the bounded integer variables in this set.
Variable const & addVariable(Variable const &variable)
Adds the given variable to this set.
bool hasVariable(std::string const &name) const
Retrieves whether this variable set contains a variable with the given name.
void substitute(std::map< storm::expressions::Variable, storm::expressions::Expression > const &substitution, bool const substituteTranscendentalNumbers)
Applies the given substitution to all variables in this set.
bool hasTransientVariable() const
Retrieves whether this variable set contains a transient variable.
void substituteExpressionVariables(std::map< storm::expressions::Variable, storm::expressions::Expression > const &substitution)
Substitutes the actual variables according to the given substitution.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
Expression iff(Expression const &first, Expression const &second)
storm::expressions::Variable cloneVariable(storm::expressions::ExpressionManager &manager, storm::expressions::Variable const &var, std::string const &variablePrefix)
storm::expressions::Expression substituteJaniExpression(storm::expressions::Expression const &expression, std::map< storm::expressions::Variable, storm::expressions::Expression > const &identifierToExpressionMap, bool const substituteTranscendentalNumbers)
boost::container::flat_set< Key, std::less< Key >, boost::container::new_allocator< Key > > FlatSet
Redefinition of flat_set was needed, because from Boost 1.70 on the default allocator is set to void.