10template<
typename ValueType,
typename StateType>
17 hasStateReward(false),
18 hasActionReward(false) {
22template<
typename ValueType,
typename StateType>
23void ImcaParserGrammar<ValueType, StateType>::initialize() {
24 value = qi::double_[qi::_val = qi::_1];
29 state = qi::as_string[qi::raw[qi::lexeme[(qi::alnum | qi::char_(
'_')) % qi::eps]]]
30 [qi::_val = phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::getStateIndex, phoenix::ref(*
this), qi::_1)];
33 reward = (-qi::lit(
"R") >> value)[qi::_val = qi::_1];
34 reward.name(
"reward");
36 transition = (qi::lit(
"*") >> state >>
37 value)[qi::_val = phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::createStateValuePair, phoenix::ref(*
this), qi::_1, qi::_2)];
38 transition.name(
"transition");
40 choicelabel = qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_(
'_')) >> *(qi::alnum | qi::char_(
'_')) | qi::lit(
"!"))]]];
41 choicelabel.name(
"choicelabel");
44 (state >> choicelabel >> -reward >>
46 qi::eps))[phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::addChoiceToStateBehavior, phoenix::ref(*
this), qi::_1, qi::_2, qi::_4, qi::_3)];
47 choice.name(
"choice");
49 transitions = qi::lit(
"#TRANSITIONS") >> *(choice);
50 transitions.name(
"TRANSITIONS");
53 qi::lit(
"#INITIALS") >> *((state >> qi::eps)[phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::addInitialState, phoenix::ref(*
this), qi::_1)]);
54 initials.name(
"INITIALS");
56 goals = qi::lit(
"#GOALS") >> *((state >> qi::eps)[phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::addGoalState, phoenix::ref(*
this), qi::_1)]);
59 start = (initials >> goals >> transitions)[qi::_val = phoenix::bind(&ImcaParserGrammar<ValueType, StateType>::createModelComponents, phoenix::ref(*
this))];
63template<
typename ValueType,
typename StateType>
64StateType ImcaParserGrammar<ValueType, StateType>::getStateIndex(std::string
const& stateString) {
65 auto it = stateIndices.find(stateString);
66 if (it == stateIndices.end()) {
67 this->stateIndices.emplace_hint(it, stateString, numStates);
69 initialStates.grow(numStates);
70 goalStates.grow(numStates);
71 markovianStates.grow(numStates);
72 stateBehaviors.resize(numStates);
79template<
typename ValueType,
typename StateType>
80std::pair<StateType, ValueType> ImcaParserGrammar<ValueType, StateType>::createStateValuePair(StateType
const& state, ValueType
const& value) {
81 return std::pair<StateType, ValueType>(state, value);
84template<
typename ValueType,
typename StateType>
85void ImcaParserGrammar<ValueType, StateType>::addInitialState(StateType
const& state) {
86 initialStates.set(state);
89template<
typename ValueType,
typename StateType>
90void ImcaParserGrammar<ValueType, StateType>::addGoalState(StateType
const& state) {
91 goalStates.set(state);
94template<
typename ValueType,
typename StateType>
95void ImcaParserGrammar<ValueType, StateType>::addChoiceToStateBehavior(StateType
const& state, std::string
const& label,
96 std::vector<std::pair<StateType, ValueType>>
const& transitions,
97 boost::optional<ValueType>
const& reward) {
98 bool isMarkovian = label ==
"!";
99 storm::generator::Choice<ValueType, StateType> choice(0, isMarkovian);
100 STORM_LOG_THROW(!transitions.empty(), storm::exceptions::WrongFormatException,
"Empty choice defined for state s" << state <<
".");
101 if (options.buildChoiceLabels && !isMarkovian) {
102 choice.addLabel(label);
104 if (reward && !isMarkovian) {
105 hasActionReward =
true;
106 choice.addReward(reward.get());
108 for (
auto const& t : transitions) {
110 "Probabilities and rates have to be positive. got " << t.second <<
" at state s" << state <<
".");
111 choice.addProbability(t.first, t.second);
114 "Probability for choice " << label <<
" on state s" << state <<
" does not sum up to one.");
117 numTransitions += choice.size();
118 auto& behavior = stateBehaviors[state];
119 behavior.setExpanded(
true);
120 behavior.addChoice(std::move(choice));
122 markovianStates.set(state);
124 hasStateReward =
true;
125 behavior.addStateReward(reward.get());
130template<
typename ValueType,
typename StateType>
131storm::storage::sparse::ModelComponents<ValueType> ImcaParserGrammar<ValueType, StateType>::createModelComponents() {
133 initialStates.resize(numStates);
134 goalStates.resize(numStates);
135 markovianStates.resize(numStates);
136 storm::models::sparse::StateLabeling stateLabeling(numStates);
137 stateLabeling.addLabel(
"init", std::move(initialStates));
138 stateLabeling.addLabel(
"goal", std::move(goalStates));
141 STORM_LOG_ASSERT(stateBehaviors.size() == numStates,
"State behavior count mismatch.");
142 if (options.fixDeadlocks) {
144 for (
auto& behavior : stateBehaviors) {
145 if (!behavior.wasExpanded()) {
146 storm::generator::Choice<ValueType, StateType> choice(0,
true);
148 behavior.setExpanded(
true);
149 behavior.addChoice(std::move(choice));
150 markovianStates.set(state);
159 storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder(numChoices, numStates, numTransitions,
true,
true, numStates);
160 std::vector<ValueType> exitRates;
161 exitRates.reserve(numStates);
162 std::optional<std::vector<ValueType>> stateRewards, actionRewards;
163 if (hasStateReward) {
166 if (hasActionReward) {
169 std::optional<storm::models::sparse::ChoiceLabeling> choiceLabeling;
170 if (options.buildChoiceLabels) {
171 choiceLabeling = storm::models::sparse::ChoiceLabeling(numChoices);
175 for (
auto const& behavior : stateBehaviors) {
176 matrixBuilder.newRowGroup(row);
177 if (!behavior.getStateRewards().empty()) {
178 STORM_LOG_ASSERT(behavior.getStateRewards().size() == 1,
"Expected single state reward.");
179 stateRewards.value()[state] = behavior.getStateRewards().front();
181 if (markovianStates.get(state)) {
183 bool markovianChoiceFound =
false;
184 for (
auto const& choice : behavior) {
185 if (choice.isMarkovian()) {
186 STORM_LOG_THROW(!markovianChoiceFound, storm::exceptions::WrongFormatException,
187 "Multiple Markovian choices defined for state " << state <<
".");
188 markovianChoiceFound =
true;
189 if (!choice.getRewards().empty()) {
190 STORM_LOG_ASSERT(choice.getRewards().size() == 1,
"Expected exactly one reward per choice.");
191 actionRewards.value()[row] = choice.getRewards().front();
193 if (options.buildChoiceLabels && choice.hasLabels()) {
194 STORM_LOG_ASSERT(choice.getLabels().size() == 1,
"Expected exactly one label per choice.");
195 std::string
const& label = *choice.getLabels().begin();
196 if (!choiceLabeling->containsLabel(label)) {
197 choiceLabeling->addLabel(label);
199 choiceLabeling->addLabelToChoice(label, row);
201 exitRates.push_back(choice.getTotalMass());
202 for (
auto const& transition : choice) {
203 matrixBuilder.addNextValue(row, transition.first,
static_cast<ValueType>(transition.second / exitRates.back()));
212 for (
auto const& choice : behavior) {
213 if (!choice.isMarkovian()) {
214 if (!choice.getRewards().empty()) {
215 STORM_LOG_ASSERT(choice.getRewards().size() == 1,
"Expected exactly one reward per choice.");
216 actionRewards.value()[row] = choice.getRewards().front();
218 if (options.buildChoiceLabels && choice.hasLabels()) {
219 STORM_LOG_ASSERT(choice.getLabels().size() == 1,
"Expected exactly one label per choice.");
220 std::string
const& label = *choice.getLabels().begin();
221 if (!choiceLabeling->containsLabel(label)) {
222 choiceLabeling->addLabel(label);
224 choiceLabeling->addLabelToChoice(label, row);
226 for (
auto const& transition : choice) {
227 matrixBuilder.addNextValue(row, transition.first, transition.second);
236 std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> rewardModel;
237 if (hasStateReward || hasActionReward) {
238 rewardModel.insert(std::make_pair(
"", storm::models::sparse::StandardRewardModel<ValueType>(stateRewards, actionRewards)));
240 storm::storage::sparse::ModelComponents<ValueType> components(matrixBuilder.build(), std::move(stateLabeling), std::move(rewardModel),
false,
241 std::move(markovianStates));
242 components.exitRates = std::move(exitRates);
243 components.choiceLabeling = std::move(choiceLabeling);
ImcaParserGrammar(ExplicitModelParserOptions const &options=ExplicitModelParserOptions())
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
Contains all file parsers and helper classes.
bool isOne(ValueType const &a)