Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
EliminateAction.cpp
Go to the documentation of this file.
1#include "EliminateAction.h"
2#include <boost/format.hpp>
3#include <boost/graph/adjacency_list.hpp>
6
7namespace storm {
8namespace jani {
9namespace elimination_actions {
10EliminateAction::EliminateAction(const std::string& automatonName, const std::string& locationName) {
11 this->automatonName = automatonName;
12 this->locationName = locationName;
13}
14
16 return (boost::format("EliminateAction (Automaton %s, Location %s)") % automatonName % locationName).str();
17}
18
20 STORM_LOG_THROW(!session.hasLoops(automatonName, locationName), storm::exceptions::InvalidArgumentException, "Locations with loops cannot be eliminated");
21
22 Automaton& automaton = session.getModel().getAutomaton(automatonName);
23 uint64_t locIndex = automaton.getLocationIndex(locationName);
24
25 // The basic idea is to iterate over the edges and eliminate those that are incident to the location.
26 // There are a few complications:
27 // - When we modify the edges, the edge container is rebuilt and we have to call automaton.getEdges()
28 // again instead of continuing with the current list of edges.
29 // - Edges are ordered according to the index of the outgoing location. This means that if we add a new
30 // edge, that doesn't append it to the end of the edge list, but inserts it somewhere into the list.
31 // - We only remove one destination per step. If an edge has two destinations leading to the location we
32 // want to eliminate, we eliminate one, add a new edge and then later visit the new edge to eliminate
33 // the other destination. This means that a single pass is not sufficient to perform elimination.
34 // The basic idea is therefore to iterate over the edges until we've completed a full iteration without
35 // performing any eliminations.
36
37 uint64_t edgeIndex = 0;
38 uint64_t stepsWithoutChange = 0;
39 std::vector<Edge>& edges = automaton.getEdges();
40 while (stepsWithoutChange <= edges.size()) {
41 Edge edge = edges[edgeIndex];
42
43 if (edge.getGuard().containsVariables() || edge.getGuard().evaluateAsBool()) {
44 uint64_t destCount = edge.getNumberOfDestinations();
45 for (uint64_t j = 0; j < destCount; j++) {
46 const EdgeDestination& dest = edge.getDestination(j);
47 if (dest.getLocationIndex() == locIndex) {
48 detail::Edges outgoingEdges = automaton.getEdgesFromLocation(locationName);
49 eliminateDestination(session, automaton, edges[edgeIndex], j, outgoingEdges);
50 // eliminateDestination adds new edges to the edge container, so we need to get the
51 // new list of edges:
52 edges = automaton.getEdges();
53 stepsWithoutChange = 0;
54 break;
55 }
56 }
57 }
58
59 edgeIndex++;
60 stepsWithoutChange++;
61 if (edgeIndex >= edges.size()) {
62 edgeIndex -= edges.size();
63 }
64 }
65
66 // The elimination is now complete. To make sure nothing went wrong, we go over all the edges one more
67 // time. If any are still incident to the location we want to eliminate, something went wrong.
68 for (Edge& edge : automaton.getEdges()) {
69 if (!edge.getGuard().containsVariables() && !edge.getGuard().evaluateAsBool())
70 continue;
71 for (const EdgeDestination& dest : edge.getDestinations()) {
72 if (dest.getLocationIndex() == locIndex) {
73 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "Could not eliminate location");
74 }
75 }
76 }
77}
78
79void EliminateAction::eliminateDestination(JaniLocalEliminator::Session& session, Automaton& automaton, Edge& edge, const uint64_t destIndex,
80 detail::Edges& outgoing) {
81 uint64_t sourceIndex = edge.getSourceLocationIndex();
82 uint64_t actionIndex = edge.getActionIndex();
83 EdgeDestination dest = edge.getDestination(destIndex);
84
85 std::vector<Edge>
86 newEdges; // Don't add the new edges immediately -- we cannot safely iterate over the outgoing edges while adding new edges to the structure
87
88 for (Edge& outEdge : outgoing) {
89 if (!outEdge.getGuard().containsVariables() && !outEdge.getGuard().evaluateAsBool())
90 continue;
91
92 expressions::Expression newGuard = session.getNewGuard(edge, dest, outEdge);
93 std::shared_ptr<storm::jani::TemplateEdge> templateEdge = std::make_shared<storm::jani::TemplateEdge>(newGuard);
94 std::vector<std::pair<uint64_t, storm::expressions::Expression>> destinationLocationsAndProbabilities;
95 for (const EdgeDestination& outDest : outEdge.getDestinations()) {
96 expressions::Expression probability = session.getProbability(dest, outDest);
97
98 OrderedAssignments oa = session.executeInSequence(dest, outDest, session.rewardModels);
99 TemplateEdgeDestination templateEdgeDestination(oa);
100 templateEdge->addDestination(templateEdgeDestination);
101
102 destinationLocationsAndProbabilities.emplace_back(outDest.getLocationIndex(), probability);
103 }
104
105 // Add remaining destinations back to the edge:
106 uint64_t destCount = edge.getNumberOfDestinations();
107 for (uint64_t i = 0; i < destCount; i++) {
108 if (i == destIndex)
109 continue;
110 const EdgeDestination& unchangedDest = edge.getDestination(i);
111 OrderedAssignments oa(unchangedDest.getOrderedAssignments().clone());
112 TemplateEdgeDestination templateEdgeDestination(oa);
113 templateEdge->addDestination(templateEdgeDestination);
114 destinationLocationsAndProbabilities.emplace_back(unchangedDest.getLocationIndex(), unchangedDest.getProbability());
115 }
116
117 STORM_LOG_THROW(!edge.hasRate() && !outEdge.hasRate(), storm::exceptions::NotImplementedException, "Edge Rates are not implemented");
118 newEdges.emplace_back(Edge(sourceIndex, actionIndex, boost::none, templateEdge, destinationLocationsAndProbabilities));
119 }
120
121 edge.setGuard(edge.getGuard().getManager().boolean(false)); // Instead of deleting the edge
122
123 for (const Edge& newEdge : newEdges) {
124 automaton.addEdge(newEdge);
125 }
126}
127} // namespace elimination_actions
128} // namespace jani
129} // namespace storm
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.
ExpressionManager const & getManager() const
Retrieves the manager responsible for this expression.
Expression boolean(bool value) const
Creates an expression that characterizes the given boolean literal.
void addEdge(Edge const &edge)
Adds an edge to the automaton.
Edges getEdgesFromLocation(std::string const &name)
Retrieves the edges of the location with the given name.
std::vector< Edge > & getEdges()
Retrieves the edges of the automaton.
uint64_t getLocationIndex(std::string const &name) const
storm::expressions::Expression const & getProbability() const
Retrieves the probability of choosing this destination.
OrderedAssignments const & getOrderedAssignments() const
Retrieves the assignments to make when choosing this destination.
uint64_t getLocationIndex() const
Retrieves the id of the destination location.
uint64_t getActionIndex() const
Retrieves the id of the action with which this edge is labeled.
Definition Edge.cpp:45
bool hasRate() const
Retrieves whether this edge has an associated rate.
Definition Edge.cpp:49
uint64_t getSourceLocationIndex() const
Retrieves the index of the source location.
Definition Edge.cpp:41
std::size_t getNumberOfDestinations() const
Retrieves the number of destinations of this edge.
Definition Edge.cpp:85
void setGuard(storm::expressions::Expression const &guard)
Sets a new guard for this edge.
Definition Edge.cpp:69
storm::expressions::Expression const & getGuard() const
Retrieves the guard of this edge.
Definition Edge.cpp:65
EdgeDestination const & getDestination(uint64_t index) const
Retrieves the destination with the given index.
Definition Edge.cpp:73
expressions::Expression getNewGuard(const Edge &edge, const EdgeDestination &dest, const Edge &outgoing)
bool hasLoops(const std::string &automatonName, std::string const &locationName)
expressions::Expression getProbability(const EdgeDestination &first, const EdgeDestination &then)
OrderedAssignments executeInSequence(const EdgeDestination &first, const EdgeDestination &then, std::set< std::string > &rewardVariables)
Automaton & getAutomaton(std::string const &name)
Retrieves the automaton with the given name.
Definition Model.cpp:888
OrderedAssignments clone() const
EliminateAction(const std::string &automatonName, const std::string &locationName)
void doAction(JaniLocalEliminator::Session &session) override
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
LabParser.cpp.
Definition cli.cpp:18