Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
EliminateAutomaticallyAction.cpp
Go to the documentation of this file.
2#include "EliminateAction.h"
3
5
6namespace storm {
7namespace jani {
8namespace elimination_actions {
10 uint32_t transitionCountThreshold, bool restrictToUnnamedActions)
11 : automatonName(automatonName),
12 eliminationOrder(order),
13 restrictToUnnamedActions(restrictToUnnamedActions),
14 transitionCountThreshold(transitionCountThreshold) {}
15
17 return "EliminateAutomaticallyAction";
18}
19
21 Automaton* automaton = &session.getModel().getAutomaton(automatonName);
22 switch (eliminationOrder) {
24 STORM_LOG_THROW(!restrictToUnnamedActions, storm::exceptions::NotImplementedException,
25 "Cannot perform automatic elimination if restrictToUnnamedActions is true and elimination order is arbitrary");
26
27 for (const auto& loc : automaton->getLocations()) {
28 if (session.isEliminable(automatonName, loc.getName())) {
29 STORM_LOG_TRACE("Eliminating location " + loc.getName());
30 EliminateAction action = EliminateAction(automatonName, loc.getName());
31 action.doAction(session);
32 }
33 }
34 break;
35 }
37 // A location is uneliminable if
38 // - it is initial
39 // - it (potentially) satisfies the property
40 // - it has already been eliminated
41 // - it has a loop
42 // After each elimination, this list is updated to account for new loops
43 std::map<std::string, bool> uneliminable;
44 STORM_LOG_TRACE("Elimination status of locations:");
45 for (const auto& loc : automaton->getLocations()) {
46 bool possiblyInitial = session.isPossiblyInitial(automatonName, loc.getName());
47 bool partOfProp = session.isPartOfProp(automatonName, loc.getName());
48 bool hasLoops = session.hasLoops(automatonName, loc.getName());
49 bool isDeadlock = automaton->getEdgesFromLocation(loc.getName()).empty();
50 bool hasNamedAction = restrictToUnnamedActions && session.hasNamedActions(automatonName, loc.getName());
51
52 bool isUneliminable = possiblyInitial || partOfProp || hasLoops || isDeadlock || hasNamedAction;
53 uneliminable.insert(std::pair<std::string, bool>(loc.getName(), isUneliminable));
54 STORM_LOG_TRACE("\t" + loc.getName() + ": " << ([&] {
55 std::string eliminationStatus = "";
56 if (isUneliminable) {
57 eliminationStatus += "Uneliminable (";
58 if (possiblyInitial)
59 eliminationStatus += "initial, ";
60 if (partOfProp)
61 eliminationStatus += "part of prop, ";
62 if (hasLoops)
63 eliminationStatus += "has loops, ";
64 if (isDeadlock)
65 eliminationStatus += "has no outgoing edges, ";
66 if (hasNamedAction)
67 eliminationStatus += "has named action, ";
68 eliminationStatus = eliminationStatus.substr(0, eliminationStatus.size() - 2) + ")";
69 } else {
70 eliminationStatus += "Eliminable";
71 }
72 return eliminationStatus;
73 })());
74 }
75 STORM_LOG_TRACE("Performing elimination");
76
77 bool done = false;
78 while (!done) {
79 uint64_t minNewEdges = 18446744073709551615U; // max value of uint64
80 int bestLocIndex = -1;
81 for (const auto& loc : automaton->getLocations()) {
82 if (uneliminable[loc.getName()])
83 continue;
84
85 auto locIndex = automaton->getLocationIndex(loc.getName());
86 uint64_t outgoing = automaton->getEdgesFromLocation(locIndex).size();
87 uint64_t incoming = 0;
88 for (const auto& edge : automaton->getEdges()) {
89 uint64_t addedTransitions = 1;
90 for (const auto& dest : edge.getDestinations()) {
91 if (dest.getLocationIndex() == locIndex) {
92 addedTransitions *= outgoing;
93 // Stop once we hit the threshold -- otherwise there is a risk of causing
94 // an overflow due to the exponential growth of addedTransitions:
95 if (addedTransitions > transitionCountThreshold) {
96 break;
97 }
98 }
99 }
100 incoming += addedTransitions - 1;
101 }
102 uint64_t newEdges = incoming * outgoing;
103
104 if (newEdges <= minNewEdges) {
105 minNewEdges = newEdges;
106 bestLocIndex = locIndex;
107 }
108 }
109
110 if (bestLocIndex == -1) {
111 done = true;
112 STORM_LOG_TRACE("Cannot eliminate more locations");
113 } else if (minNewEdges > transitionCountThreshold) {
114 done = true;
115 STORM_LOG_TRACE("Cannot eliminate more locations without creating too many new transitions (best: " + std::to_string(minNewEdges) +
116 " new transitions)");
117 } else {
118 std::string locName = automaton->getLocation(bestLocIndex).getName();
119 STORM_LOG_TRACE("\tEliminating location " + locName + " (" + std::to_string(minNewEdges) + " new edges)");
120 EliminateAction action = EliminateAction(automatonName, locName);
121 action.doAction(session);
122 automaton = &session.getModel().getAutomaton(automatonName);
123 uneliminable[locName] = true;
124
125 // Update "uneliminable" to account for potential new loops
126 for (const auto& loc : automaton->getLocations()) {
127 if (!uneliminable[loc.getName()]) {
128 if (session.hasLoops(automatonName, loc.getName())) {
129 uneliminable[loc.getName()] = true;
130 STORM_LOG_TRACE("\t" + loc.getName() + " now has a loop");
131 }
132 if (restrictToUnnamedActions && session.hasNamedActions(automatonName, loc.getName())) {
133 uneliminable[loc.getName()] = true;
134 STORM_LOG_TRACE("\t" + loc.getName() + " now has a named action");
135 }
136 }
137 }
138 }
139 }
140
141 break;
142 }
143 default: {
144 STORM_LOG_THROW(true, storm::exceptions::NotImplementedException, "This elimination order is not yet implemented");
145 break;
146 }
147 }
148}
149} // namespace elimination_actions
150} // namespace jani
151} // namespace storm
Location const & getLocation(uint64_t index) const
Retrieves the location with the given index.
std::vector< Location > const & getLocations() const
Retrieves the locations of the automaton.
Definition Automaton.cpp:98
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
bool hasLoops(const std::string &automatonName, std::string const &locationName)
bool hasNamedActions(const std::string &automatonName, std::string const &locationName)
bool isPartOfProp(const std::string &automatonName, std::string const &locationName)
bool isPossiblyInitial(const std::string &automatonName, std::string const &locationName)
bool isEliminable(const std::string &automatonName, std::string const &locationName)
std::string const & getName() const
Retrieves the name of the location.
Definition Location.cpp:19
Automaton & getAutomaton(std::string const &name)
Retrieves the automaton with the given name.
Definition Model.cpp:888
std::size_t size() const
Retrieves the number of edges.
void doAction(JaniLocalEliminator::Session &session) override
void doAction(JaniLocalEliminator::Session &session) override
EliminateAutomaticallyAction(const std::string &automatonName, EliminationOrder eliminationOrder, uint32_t transitionCountThreshold=1000, bool restrictToUnnamedActions=false)
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
LabParser.cpp.
Definition cli.cpp:18