Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ImcaMarkovAutomatonParserGrammar.cpp
Go to the documentation of this file.
2
4#include "storm/io/file.h"
8
9namespace storm {
10namespace parser {
11
12template<typename ValueType, typename StateType>
14 : ImcaParserGrammar<ValueType, StateType>::base_type(start), numStates(0), numChoices(0), numTransitions(0), hasStateReward(false), hasActionReward(false) {
15 buildChoiceLabels = storm::settings::getModule<storm::settings::modules::BuildSettings>().isBuildChoiceLabelsSet();
16 initialize();
17}
18
19template<typename ValueType, typename StateType>
21 value = qi::double_[qi::_val = qi::_1];
22 value.name("value");
23
24 // We assume here that imca files are alphanumeric strings, If we restrict ourselves to the 's12345' representation, we could also do:
25 // state = (qi::lit("s") > qi::ulong_)[qi::_val = qi::_1];
26 state = qi::as_string[qi::raw[qi::lexeme[(qi::alnum | qi::char_('_')) % qi::eps]]]
27 [qi::_val = phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::getStateIndex, phoenix::ref(*this), qi::_1)];
28 state.name("state");
29
30 reward = (-qi::lit("R") >> value)[qi::_val = qi::_1];
31 reward.name("reward");
32
33 transition = (qi::lit("*") >> state >>
34 value)[qi::_val = phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::createStateValuePair, phoenix::ref(*this), qi::_1, qi::_2)];
35 transition.name("transition");
36
37 choicelabel = qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')) | qi::lit("!"))]]];
38 choicelabel.name("choicelabel");
39
40 choice =
41 (state >> choicelabel >> -reward >>
42 *(transition >>
43 qi::eps))[phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::addChoiceToStateBehavior, phoenix::ref(*this), qi::_1, qi::_2, qi::_4, qi::_3)];
44 choice.name("choice");
45
46 transitions = qi::lit("#TRANSITIONS") >> *(choice);
47 transitions.name("TRANSITIONS");
48
49 initials =
50 qi::lit("#INITIALS") >> *((state >> qi::eps)[phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::addInitialState, phoenix::ref(*this), qi::_1)]);
51 initials.name("INITIALS");
52
53 goals = qi::lit("#GOALS") >> *((state >> qi::eps)[phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::addGoalState, phoenix::ref(*this), qi::_1)]);
54 goals.name("GOALS");
55
56 start = (initials >> goals >> transitions)[qi::_val = phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::createModelComponents, phoenix::ref(*this))];
57 start.name("start");
58}
59
60template<typename ValueType, typename StateType>
61StateType ImcaParserGrammar<ValueType, StateType>::getStateIndex(std::string const& stateString) {
62 auto it = stateIndices.find(stateString);
63 if (it == stateIndices.end()) {
64 this->stateIndices.emplace_hint(it, stateString, numStates);
65 ++numStates;
66 initialStates.grow(numStates);
67 goalStates.grow(numStates);
68 markovianStates.grow(numStates);
69 stateBehaviors.resize(numStates);
70 return numStates - 1;
71 } else {
72 return it->second;
73 }
74}
75
76template<typename ValueType, typename StateType>
77std::pair<StateType, ValueType> ImcaParserGrammar<ValueType, StateType>::createStateValuePair(StateType const& state, ValueType const& value) {
78 return std::pair<StateType, ValueType>(state, value);
79}
80
81template<typename ValueType, typename StateType>
82void ImcaParserGrammar<ValueType, StateType>::addInitialState(StateType const& state) {
83 initialStates.set(state);
84}
85
86template<typename ValueType, typename StateType>
87void ImcaParserGrammar<ValueType, StateType>::addGoalState(StateType const& state) {
88 goalStates.set(state);
89}
90
91template<typename ValueType, typename StateType>
92void ImcaParserGrammar<ValueType, StateType>::addChoiceToStateBehavior(StateType const& state, std::string const& label,
93 std::vector<std::pair<StateType, ValueType>> const& transitions,
94 boost::optional<ValueType> const& reward) {
95 bool isMarkovian = label == "!";
97 STORM_LOG_THROW(!transitions.empty(), storm::exceptions::WrongFormatException, "Empty choice defined for state s" << state << ".");
98 if (buildChoiceLabels && !isMarkovian) {
99 choice.addLabel(label);
100 }
101 if (reward && !isMarkovian) {
102 hasActionReward = true;
103 choice.addReward(reward.get());
104 }
105 for (auto const& t : transitions) {
106 STORM_LOG_THROW(t.second > storm::utility::zero<ValueType>(), storm::exceptions::WrongFormatException,
107 "Probabilities and rates have to be positive. got " << t.second << " at state s" << state << ".");
108 choice.addProbability(t.first, t.second);
109 }
110 STORM_LOG_THROW(isMarkovian || storm::utility::isOne(choice.getTotalMass()), storm::exceptions::WrongFormatException,
111 "Probability for choice " << label << " on state s" << state << " does not sum up to one.");
112
113 ++numChoices;
114 numTransitions += choice.size();
115 auto& behavior = stateBehaviors[state];
116 behavior.setExpanded(true);
117 behavior.addChoice(std::move(choice));
118 if (isMarkovian) {
119 markovianStates.set(state);
120 if (reward) {
121 hasStateReward = true;
122 behavior.addStateReward(reward.get());
123 }
124 }
125}
126
127template<typename ValueType, typename StateType>
128storm::storage::sparse::ModelComponents<ValueType> ImcaParserGrammar<ValueType, StateType>::createModelComponents() {
129 // Prepare the statelabeling
130 initialStates.resize(numStates);
131 goalStates.resize(numStates);
132 markovianStates.resize(numStates);
133 storm::models::sparse::StateLabeling stateLabeling(numStates);
134 stateLabeling.addLabel("init", std::move(initialStates));
135 stateLabeling.addLabel("goal", std::move(goalStates));
136
137 // Fix deadlocks (if required)
138 assert(stateBehaviors.size() == numStates);
140 StateType state = 0;
141 for (auto& behavior : stateBehaviors) {
142 if (!behavior.wasExpanded()) {
144 choice.addProbability(state, storm::utility::one<ValueType>());
145 behavior.setExpanded(true);
146 behavior.addChoice(std::move(choice));
147 markovianStates.set(state);
148 ++numChoices;
149 ++numTransitions;
150 }
151 ++state;
152 }
153 }
154
155 // Build the transition matrix together with exit rates, reward models, and choice labeling
156 storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder(numChoices, numStates, numTransitions, true, true, numStates);
157 std::vector<ValueType> exitRates;
158 exitRates.reserve(numStates);
159 std::optional<std::vector<ValueType>> stateRewards, actionRewards;
160 if (hasStateReward) {
161 stateRewards = std::vector<ValueType>(numStates, storm::utility::zero<ValueType>());
162 }
163 if (hasActionReward) {
164 actionRewards = std::vector<ValueType>(numChoices, storm::utility::zero<ValueType>());
165 }
166 std::optional<storm::models::sparse::ChoiceLabeling> choiceLabeling;
167 if (buildChoiceLabels) {
168 choiceLabeling = storm::models::sparse::ChoiceLabeling(numChoices);
169 }
170 StateType state = 0;
171 StateType row = 0;
172 for (auto const& behavior : stateBehaviors) {
173 matrixBuilder.newRowGroup(row);
174 if (!behavior.getStateRewards().empty()) {
175 assert(behavior.getStateRewards().size() == 1);
176 stateRewards.value()[state] = behavior.getStateRewards().front();
177 }
178 if (markovianStates.get(state)) {
179 // For Markovian states, the Markovian choice has to be the first one in the resulting transition matrix.
180 bool markovianChoiceFound = false;
181 for (auto const& choice : behavior) {
182 if (choice.isMarkovian()) {
183 STORM_LOG_THROW(!markovianChoiceFound, storm::exceptions::WrongFormatException,
184 "Multiple Markovian choices defined for state " << state << ".");
185 markovianChoiceFound = true;
186 if (!choice.getRewards().empty()) {
187 assert(choice.getRewards().size() == 1);
188 actionRewards.value()[row] = choice.getRewards().front();
189 }
190 if (buildChoiceLabels && choice.hasLabels()) {
191 assert(choice.getLabels().size() == 1);
192 std::string const& label = *choice.getLabels().begin();
193 if (!choiceLabeling->containsLabel(label)) {
194 choiceLabeling->addLabel(label);
195 }
196 choiceLabeling->addLabelToChoice(label, row);
197 }
198 exitRates.push_back(choice.getTotalMass());
199 for (auto const& transition : choice) {
200 matrixBuilder.addNextValue(row, transition.first, static_cast<ValueType>(transition.second / exitRates.back()));
201 }
202 ++row;
203 }
204 }
205 } else {
206 exitRates.push_back(storm::utility::zero<ValueType>());
207 }
208 // Now add all probabilistic choices.
209 for (auto const& choice : behavior) {
210 if (!choice.isMarkovian()) {
211 if (!choice.getRewards().empty()) {
212 assert(choice.getRewards().size() == 1);
213 actionRewards.value()[row] = choice.getRewards().front();
214 }
215 if (buildChoiceLabels && choice.hasLabels()) {
216 assert(choice.getLabels().size() == 1);
217 std::string const& label = *choice.getLabels().begin();
218 if (!choiceLabeling->containsLabel(label)) {
219 choiceLabeling->addLabel(label);
220 }
221 choiceLabeling->addLabelToChoice(label, row);
222 }
223 for (auto const& transition : choice) {
224 matrixBuilder.addNextValue(row, transition.first, transition.second);
225 }
226 ++row;
227 }
228 }
229 ++state;
230 }
231
232 // Finalize the model components
233 std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> rewardModel;
234 if (hasStateReward || hasActionReward) {
235 rewardModel.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<ValueType>(stateRewards, actionRewards)));
236 }
237 storm::storage::sparse::ModelComponents<ValueType> components(matrixBuilder.build(), std::move(stateLabeling), std::move(rewardModel), false,
238 std::move(markovianStates));
239 components.exitRates = std::move(exitRates);
240 components.choiceLabeling = std::move(choiceLabeling);
241
242 return components;
243}
244
245template class ImcaParserGrammar<double>;
246} // namespace parser
247} // namespace storm
This class manages the labeling of the choice space with a number of (atomic) labels.
This class manages the labeling of the state space with a number of (atomic) labels.
A class that can be used to build a sparse matrix by adding value by value.
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SFTBDDChecker::ValueType ValueType
SettingsType const & getModule()
Get module.
bool isOne(ValueType const &a)
Definition constants.cpp:36
LabParser.cpp.
Definition cli.cpp:18