11 :
FormulaParserGrammar::base_type(start), constManager(manager), manager(nullptr), expressionParser(*manager, keywords_, true, true), propertyCount(0) {
16 :
FormulaParserGrammar::base_type(start), constManager(manager), manager(manager), expressionParser(*manager, keywords_, true, true), propertyCount(0) {
24void FormulaParserGrammar::initialize() {
26 for (
auto variableTypePair : *constManager) {
32 keywords_.name(
"keyword");
33 nonStandardKeywords_.name(
"non-standard Storm-specific keyword");
34 relationalOperator_.name(
"relational operator");
35 optimalityOperator_.name(
"optimality operator");
36 operatorKeyword_.name(
"Operator keyword");
37 filterType_.name(
"filter type");
40 isPathFormula = qi::eps(qi::_r1 == FormulaKind::Path);
41 noAmbiguousNonAssociativeOperator =
42 !(qi::lit(qi::_r2)[qi::_pass = phoenix::bind(&FormulaParserGrammar::raiseAmbiguousNonAssociativeOperatorError, phoenix::ref(*
this), qi::_r1, qi::_r2)]);
43 noAmbiguousNonAssociativeOperator.name(
"no ambiguous non-associative operator");
44 identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_(
'_') | qi::char_(
'.')) >> *(qi::alnum | qi::char_(
'_')))]]];
45 identifier.name(
"identifier");
46 label %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_(
'_')) >> *(qi::alnum | qi::char_(
'_')))]]];
48 quotedString %= qi::as_string[qi::lexeme[qi::omit[qi::char_(
'"')] > qi::raw[*(!qi::char_(
'"') >> qi::char_)] > qi::omit[qi::lit(
'"')]]];
49 quotedString.name(
"quoted string");
53 (-optimalityOperator_)[qi::_a = qi::_1] >>
55 qi::lit(
"?"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createOperatorInformation, phoenix::ref(*
this), qi::_a, boost::none, boost::none)] |
56 (relationalOperator_ >
57 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createOperatorInformation, phoenix::ref(*
this), qi::_a, qi::_1, qi::_2)]);
58 operatorInformation.name(
"operator information");
62 (longRunAverageRewardFormula | eventuallyFormula(qi::_r1) | discountedCumulativeRewardFormula | discountedTotalRewardFormula |
63 cumulativeRewardFormula | instantaneousRewardFormula | totalRewardFormula)) |
68 phoenix::ref(*
this), qi::_1, qi::_2, qi::_r1)];
69 operatorSubFormula.name(
"operator subformula");
71 rewardModelName.name(
"reward model name");
73 (operatorKeyword_[qi::_a = qi::_1] > -rewardModelName(qi::_a) > operatorInformation > qi::lit(
"[") > operatorSubFormula(qi::_a) >
74 qi::lit(
"]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createOperatorFormula, phoenix::ref(*
this), qi::_a, qi::_2, qi::_3, qi::_4)];
75 operatorFormula.name(
"operator formula");
79 (qi::lit(
"\"") >> label >> qi::lit(
"\""))[qi::_val = phoenix::bind(&FormulaParserGrammar::createAtomicLabelFormula, phoenix::ref(*
this), qi::_1)];
80 labelFormula.name(
"label formula");
81 expressionFormula = expressionParser[qi::_val = phoenix::bind(&FormulaParserGrammar::createAtomicExpressionFormula, phoenix::ref(*
this), qi::_1)];
82 expressionFormula.name(
"expression formula");
84 basicPropositionalFormula =
88 (formula(qi::_r1, qi::_r2) > qi::lit(
")")))
89 | labelFormula | negationPropositionalFormula(qi::_r1, qi::_r2) | operatorFormula |
90 (isPathFormula(qi::_r1) >> prefixOperatorPathFormula(qi::_r2))
91 | multiLexOperatorFormula
92 | multiOperatorFormula
93 | quantileFormula | gameFormula;
98 negationPropositionalFormula =
100 basicPropositionalFormula(qi::_r1, qi::_r2))[qi::_val = phoenix::bind(&FormulaParserGrammar::createUnaryBooleanStateOrPathFormula, phoenix::ref(*
this),
102 basicPropositionalFormula.name(
"basic propositional formula");
103 andLevelPropositionalFormula =
104 basicPropositionalFormula(qi::_r1, qi::_r2)[qi::_val = qi::_1] >>
105 *(qi::lit(
"&") > basicPropositionalFormula(
106 qi::_r1, qi::_r2)[qi::_val = phoenix::bind(&FormulaParserGrammar::createBinaryBooleanStateOrPathFormula, phoenix::ref(*
this),
107 qi::_val, qi::_1, storm::logic::BinaryBooleanStateFormula::OperatorType::And)]);
108 andLevelPropositionalFormula.name(
"and precedence level propositional formula");
109 orLevelPropositionalFormula =
110 andLevelPropositionalFormula(qi::_r1, qi::_r2)[qi::_val = qi::_1] >>
111 *((!qi::lit(
"||") >> qi::lit(
"|"))
112 > andLevelPropositionalFormula(
113 qi::_r1, qi::_r2)[qi::_val = phoenix::bind(&FormulaParserGrammar::createBinaryBooleanStateOrPathFormula, phoenix::ref(*
this), qi::_val, qi::_1,
114 storm::logic::BinaryBooleanStateFormula::OperatorType::Or)]);
115 orLevelPropositionalFormula.name(
"or precedence level propositional formula");
116 propositionalFormula = orLevelPropositionalFormula(qi::_r1, qi::_r2);
120 basicPathFormula = propositionalFormula(FormulaKind::Path, qi::_r1)
121 | prefixOperatorPathFormula(
123 prefixOperatorPathFormula =
124 eventuallyFormula(qi::_r1) | nextFormula(qi::_r1) | globallyFormula(qi::_r1) | hoaPathFormula(qi::_r1) | multiBoundedPathFormula(qi::_r1);
125 basicPathFormula.name(
"basic path formula");
137 timeBoundReference.name(
"time bound reference");
138 timeBound = ((timeBoundReference >> qi::lit(
"[")) > expressionParser > qi::lit(
",") > expressionParser >
139 qi::lit(
"]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundFromInterval, phoenix::ref(*
this), qi::_2, qi::_3, qi::_1)] |
140 (timeBoundReference >> (qi::lit(
"<=")[(qi::_a =
true, qi::_b =
false)] | qi::lit(
"<")[(qi::_a =
true, qi::_b =
true)] |
141 qi::lit(
">=")[(qi::_a =
false, qi::_b =
false)] | qi::lit(
">")[(qi::_a =
false, qi::_b =
true)]) >>
142 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundFromSingleBound, phoenix::ref(*
this), qi::_2, qi::_a, qi::_b,
144 (timeBoundReference >> qi::lit(
"=") >>
145 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundFromInterval, phoenix::ref(*
this), qi::_2, qi::_2, qi::_1)];
146 timeBound.name(
"time bound");
147 timeBounds = (timeBound % qi::lit(
",")) | (((-qi::lit(
"^") >> qi::lit(
"{")) >> (timeBound % qi::lit(
","))) >> qi::lit(
"}"));
148 timeBounds.name(
"time bounds");
150 (qi::lit(
"F") > (-timeBounds) >
151 basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createEventuallyFormula, phoenix::ref(*
this), qi::_1, qi::_r1, qi::_2)];
152 eventuallyFormula.name(
"eventually formula");
153 nextFormula = (qi::lit(
"X") > basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createNextFormula, phoenix::ref(*
this), qi::_1)];
154 nextFormula.name(
"next formula");
156 (qi::lit(
"G") > basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createGloballyFormula, phoenix::ref(*
this), qi::_1)];
157 globallyFormula.name(
"globally formula");
159 qi::lit(
"HOA:") > qi::lit(
"{") > quotedString[qi::_val = phoenix::bind(&FormulaParserGrammar::createHOAPathFormula, phoenix::ref(*
this), qi::_1)] >>
160 *(qi::lit(
",") > quotedString > qi::lit(
"->") >
161 formula(FormulaKind::State, qi::_r1))[phoenix::bind(&FormulaParserGrammar::addHoaAPMapping, phoenix::ref(*
this), *qi::_val, qi::_1, qi::_2)] >
163 multiBoundedPathFormulaOperand = pathFormula(
164 qi::_r1)[qi::_pass = phoenix::bind(&FormulaParserGrammar::isValidMultiBoundedPathFormulaOperand, phoenix::ref(*
this), qi::_1)][qi::_val = qi::_1];
165 multiBoundedPathFormulaOperand.name(
"multi bounded path formula operand");
166 multiBoundedPathFormula = ((qi::lit(
"multi") > qi::lit(
"(")) >> (multiBoundedPathFormulaOperand(qi::_r1) % qi::lit(
",")) >>
167 qi::lit(
")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createMultiBoundedPathFormula, phoenix::ref(*
this), qi::_1)];
168 multiBoundedPathFormula.name(
"multi bounded path formula");
169 untilLevelPathFormula =
170 basicPathFormula(qi::_r1)[qi::_val = qi::_1] >>
171 -((qi::lit(
"U") > (-timeBounds) >
172 basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createUntilFormula, phoenix::ref(*
this), qi::_val, qi::_1, qi::_2)]) >>
173 (qi::eps > noAmbiguousNonAssociativeOperator(qi::_val, std::string(
"U")));
174 untilLevelPathFormula.name(
"until precedence level path formula");
175 pathFormula = untilLevelPathFormula(qi::_r1);
176 pathFormula.name(
"path formula");
179 discountedTotalRewardFormula =
180 (qi::lit(
"Cdiscount=") >>
181 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createDiscountedTotalRewardFormula, phoenix::ref(*
this), qi::_1)];
182 discountedTotalRewardFormula.name(
"discounted total reward formula");
183 discountedCumulativeRewardFormula =
184 (qi::lit(
"C") >> timeBounds >> qi::lit(
"discount=") >>
185 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createDiscountedCumulativeRewardFormula, phoenix::ref(*
this), qi::_2, qi::_1)];
186 discountedCumulativeRewardFormula.name(
"discounted cumulative reward formula");
187 longRunAverageRewardFormula = (qi::lit(
"LRA") | qi::lit(
"S") |
188 qi::lit(
"MP"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createLongRunAverageRewardFormula, phoenix::ref(*
this))];
189 longRunAverageRewardFormula.name(
"long run average reward formula");
190 instantaneousRewardFormula =
191 (qi::lit(
"I=") > expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createInstantaneousRewardFormula, phoenix::ref(*
this), qi::_1)];
192 instantaneousRewardFormula.name(
"instantaneous reward formula");
193 cumulativeRewardFormula =
194 (qi::lit(
"C") >> timeBounds)[qi::_val = phoenix::bind(&FormulaParserGrammar::createCumulativeRewardFormula, phoenix::ref(*
this), qi::_1)];
195 cumulativeRewardFormula.name(
"cumulative reward formula");
196 totalRewardFormula = (qi::lit(
"C"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTotalRewardFormula, phoenix::ref(*
this))];
197 totalRewardFormula.name(
"total reward formula");
200 playerCoalition = (-((identifier[phoenix::push_back(qi::_a, qi::_1)] | qi::uint_[phoenix::push_back(qi::_a, qi::_1)]) %
201 ','))[qi::_val = phoenix::bind(&FormulaParserGrammar::createPlayerCoalition, phoenix::ref(*
this), qi::_a)];
202 playerCoalition.name(
"player coalition");
203 gameFormula = (qi::lit(
"<<") > playerCoalition > qi::lit(
">>") >
204 operatorFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createGameFormula, phoenix::ref(*
this), qi::_1, qi::_2)];
205 gameFormula.name(
"game formula");
208 multiOperatorFormula = (qi::lit(
"multi") > qi::lit(
"(") > (operatorFormula % qi::lit(
",")) >
209 qi::lit(
")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createMultiOperatorFormula, phoenix::ref(*
this), qi::_1,
211 multiOperatorFormula.name(
"multi-objective operator formula");
212 multiLexOperatorFormula = (qi::lit(
"multilex") > qi::lit(
"(") > (operatorFormula % qi::lit(
",")) >
213 qi::lit(
")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createMultiOperatorFormula, phoenix::ref(*
this), qi::_1,
215 multiLexOperatorFormula.name(
"multi-objective lexicographic operator formula");
216 quantileBoundVariable = (-optimalityOperator_ >> identifier >>
217 qi::lit(
","))[qi::_val = phoenix::bind(&FormulaParserGrammar::createQuantileBoundVariables, phoenix::ref(*
this), qi::_1, qi::_2)];
218 quantileBoundVariable.name(
"quantile bound variable");
219 quantileFormula = (qi::lit(
"quantile") > qi::lit(
"(") > *(quantileBoundVariable) >
220 operatorFormula[qi::_pass = phoenix::bind(&FormulaParserGrammar::isBooleanReturnType, phoenix::ref(*
this), qi::_1,
true)] >
221 qi::lit(
")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createQuantileFormula, phoenix::ref(*
this), qi::_1, qi::_2)];
222 quantileFormula.name(
"Quantile formula");
225 formula = (isPathFormula(qi::_r1) >> pathFormula(qi::_r2) | propositionalFormula(qi::_r1, qi::_r2));
226 formula.name(
"formula");
229 topLevelFormula.name(
"top-level formula");
231 formulaName = qi::lit(
"\"") >> identifier >> qi::lit(
"\"") >> qi::lit(
":");
232 formulaName.name(
"formula name");
237 identifier >> -(qi::lit(
"=") > expressionParser))[phoenix::bind(&FormulaParserGrammar::addConstant, phoenix::ref(*
this), qi::_1, qi::_a, qi::_2)];
238 constantDefinition.name(
"constant definition");
240#pragma clang diagnostic push
241#pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses"
244 (-formulaName >> qi::lit(
"filter") > qi::lit(
"(") > filterType_ > qi::lit(
",") > topLevelFormula > qi::lit(
",") >
246 qi::lit(
")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createProperty, phoenix::ref(*
this), qi::_1, qi::_2, qi::_3, qi::_4)] |
248 topLevelFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createPropertyWithDefaultFilterTypeAndStates, phoenix::ref(*
this), qi::_1, qi::_2)];
249 filterProperty.name(
"filter property");
251#pragma clang diagnostic pop
253 start = (qi::eps >> filterProperty[phoenix::push_back(qi::_val, qi::_1)] |
254 qi::eps(phoenix::bind(&FormulaParserGrammar::areConstantDefinitionsAllowed, phoenix::ref(*
this))) >> constantDefinition | qi::eps) %
255 +(qi::char_(
"\n;")) >>
256 qi::skip(storm::spirit_encoding::space_type() | qi::lit(
"//") >> *(qi::char_ - (qi::eol | qi::eoi)))[qi::eps] >> qi::eoi;
301 qi::on_error<qi::fail>(rewardModelName, handler(qi::_1, qi::_2, qi::_3, qi::_4));
302 qi::on_error<qi::fail>(operatorFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
303 qi::on_error<qi::fail>(labelFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
304 qi::on_error<qi::fail>(expressionFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
305 qi::on_error<qi::fail>(basicPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
306 qi::on_error<qi::fail>(negationPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
307 qi::on_error<qi::fail>(andLevelPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
308 qi::on_error<qi::fail>(orLevelPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
309 qi::on_error<qi::fail>(propositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
310 qi::on_error<qi::fail>(timeBoundReference, handler(qi::_1, qi::_2, qi::_3, qi::_4));
311 qi::on_error<qi::fail>(timeBound, handler(qi::_1, qi::_2, qi::_3, qi::_4));
312 qi::on_error<qi::fail>(timeBounds, handler(qi::_1, qi::_2, qi::_3, qi::_4));
313 qi::on_error<qi::fail>(eventuallyFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
314 qi::on_error<qi::fail>(nextFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
315 qi::on_error<qi::fail>(globallyFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
316 qi::on_error<qi::fail>(hoaPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
317 qi::on_error<qi::fail>(multiBoundedPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
318 qi::on_error<qi::fail>(prefixOperatorPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
319 qi::on_error<qi::fail>(basicPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
320 qi::on_error<qi::fail>(untilLevelPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
321 qi::on_error<qi::fail>(pathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
322 qi::on_error<qi::fail>(longRunAverageRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
323 qi::on_error<qi::fail>(instantaneousRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
324 qi::on_error<qi::fail>(cumulativeRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
325 qi::on_error<qi::fail>(totalRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
326 qi::on_error<qi::fail>(discountedCumulativeRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
327 qi::on_error<qi::fail>(discountedTotalRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
328 qi::on_error<qi::fail>(playerCoalition, handler(qi::_1, qi::_2, qi::_3, qi::_4));
329 qi::on_error<qi::fail>(gameFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
330 qi::on_error<qi::fail>(multiOperatorFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
331 qi::on_error<qi::fail>(multiLexOperatorFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
332 qi::on_error<qi::fail>(quantileBoundVariable, handler(qi::_1, qi::_2, qi::_3, qi::_4));
333 qi::on_error<qi::fail>(quantileFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
334 qi::on_error<qi::fail>(formula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
335 qi::on_error<qi::fail>(topLevelFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
336 qi::on_error<qi::fail>(formulaName, handler(qi::_1, qi::_2, qi::_3, qi::_4));
337 qi::on_error<qi::fail>(filterProperty, handler(qi::_1, qi::_2, qi::_3, qi::_4));
338 qi::on_error<qi::fail>(constantDefinition, handler(qi::_1, qi::_2, qi::_3, qi::_4));
339 qi::on_error<qi::fail>(start, handler(qi::_1, qi::_2, qi::_3, qi::_4));
344 "Identifier `" << identifier <<
"' coincides with a reserved keyword or operator. Property expressions using the variable or constant '"
345 << identifier <<
"' will not be parsed correctly.");
347 "Identifier `" << identifier <<
"' coincides with a reserved keyword or operator. Property expressions using the variable or constant '"
348 << identifier <<
"' might not be parsed correctly.");
349 this->identifiers_.add(identifier, expression);
352void FormulaParserGrammar::addConstant(std::string
const& name,
ConstantDataType type, boost::optional<storm::expressions::Expression>
const& expression) {
353 STORM_LOG_ASSERT(manager,
"Mutable expression manager required to define new constants.");
355 STORM_LOG_THROW(!manager->hasVariable(name), storm::exceptions::WrongFormatException,
356 "Invalid constant definition '" << name <<
"' in property: variable already exists.");
359 newVariable = manager->declareBooleanVariable(name);
361 newVariable = manager->declareIntegerVariable(name);
363 newVariable = manager->declareRationalVariable(name);
369 undefinedConstants.insert(newVariable);
374bool FormulaParserGrammar::areConstantDefinitionsAllowed()
const {
375 return static_cast<bool>(manager);
378std::shared_ptr<storm::logic::TimeBoundReference> FormulaParserGrammar::createTimeBoundReference(
storm::logic::TimeBoundType const& type,
379 boost::optional<std::string>
const& rewardModelName)
const {
381 return std::make_shared<storm::logic::TimeBoundReference>(rewardModelName);
383 return std::make_shared<storm::logic::TimeBoundReference>(type);
387std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>, std::shared_ptr<storm::logic::TimeBoundReference>>
389 std::shared_ptr<storm::logic::TimeBoundReference>
const& timeBoundReference)
const {
394 return std::make_tuple(lower, upper, timeBoundReference);
397std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>, std::shared_ptr<storm::logic::TimeBoundReference>>
399 std::shared_ptr<storm::logic::TimeBoundReference>
const& timeBoundReference)
const {
408std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createInstantaneousRewardFormula(
storm::expressions::Expression const& timeBound)
const {
412std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createCumulativeRewardFormula(
413 std::vector<std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>,
414 std::shared_ptr<storm::logic::TimeBoundReference>>>
const& timeBounds)
const {
415 std::vector<storm::logic::TimeBound> bounds;
416 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
417 for (
auto const& timeBound : timeBounds) {
418 STORM_LOG_THROW(!std::get<0>(timeBound), storm::exceptions::WrongFormatException,
"Cumulative reward formulas with lower time bound are not allowed.");
419 STORM_LOG_THROW(std::get<1>(timeBound), storm::exceptions::WrongFormatException,
"Cumulative reward formulas require an upper bound.");
420 bounds.push_back(std::get<1>(timeBound).get());
421 timeBoundReferences.emplace_back(*std::get<2>(timeBound));
426std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createDiscountedCumulativeRewardFormula(
428 std::vector<std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>,
429 std::shared_ptr<storm::logic::TimeBoundReference>>>
const& timeBounds)
const {
430 std::vector<storm::logic::TimeBound> bounds;
431 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
432 for (
auto const& timeBound : timeBounds) {
433 STORM_LOG_THROW(!std::get<0>(timeBound), storm::exceptions::WrongFormatException,
"Cumulative reward formulas with lower time bound are not allowed.");
434 STORM_LOG_THROW(std::get<1>(timeBound), storm::exceptions::WrongFormatException,
"Cumulative reward formulas require an upper bound.");
435 bounds.push_back(std::get<1>(timeBound).get());
436 timeBoundReferences.emplace_back(*std::get<2>(timeBound));
441std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createTotalRewardFormula()
const {
445std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createDiscountedTotalRewardFormula(
450std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createLongRunAverageRewardFormula()
const {
454std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createAtomicExpressionFormula(
storm::expressions::Expression const& expression)
const {
456 "Expected expression " + expression.
toString() +
" to be of boolean type.");
463std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBooleanLiteralFormula(
bool literal)
const {
467std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createAtomicLabelFormula(std::string
const& label)
const {
471std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createEventuallyFormula(
472 boost::optional<std::vector<std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>,
473 std::shared_ptr<storm::logic::TimeBoundReference>>>>
const& timeBounds,
475 if (timeBounds && !timeBounds.get().empty()) {
476 std::vector<boost::optional<storm::logic::TimeBound>> lowerBounds, upperBounds;
477 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
478 for (
auto const& timeBound : timeBounds.get()) {
479 lowerBounds.push_back(std::get<0>(timeBound));
480 upperBounds.push_back(std::get<1>(timeBound));
481 timeBoundReferences.emplace_back(*std::get<2>(timeBound));
483 return std::shared_ptr<storm::logic::Formula const>(
490std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createGloballyFormula(std::shared_ptr<storm::logic::Formula const>
const& subformula)
const {
494std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createNextFormula(std::shared_ptr<storm::logic::Formula const>
const& subformula)
const {
498std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUntilFormula(
499 std::shared_ptr<storm::logic::Formula const>
const& leftSubformula,
500 boost::optional<std::vector<std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>,
501 std::shared_ptr<storm::logic::TimeBoundReference>>>>
const& timeBounds,
502 std::shared_ptr<storm::logic::Formula const>
const& rightSubformula) {
503 if (timeBounds && !timeBounds.get().empty()) {
504 std::vector<boost::optional<storm::logic::TimeBound>> lowerBounds, upperBounds;
505 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
506 for (
auto const& timeBound : timeBounds.get()) {
507 lowerBounds.push_back(std::get<0>(timeBound));
508 upperBounds.push_back(std::get<1>(timeBound));
509 timeBoundReferences.emplace_back(*std::get<2>(timeBound));
511 return std::shared_ptr<storm::logic::Formula const>(
518std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createHOAPathFormula(std::string
const& automatonFile)
const {
522void FormulaParserGrammar::addHoaAPMapping(
storm::logic::Formula const& hoaFormula,
const std::string& ap,
523 std::shared_ptr<storm::logic::Formula const>& expression)
const {
530std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createConditionalFormula(
531 std::shared_ptr<storm::logic::Formula const>
const& leftSubformula, boost::optional<std::shared_ptr<storm::logic::Formula const>>
const& rightSubformula,
533 if (rightSubformula) {
537 return leftSubformula;
542 boost::optional<storm::logic::ComparisonType>
const& comparisonType,
543 boost::optional<storm::expressions::Expression>
const& threshold)
const {
544 if (comparisonType && threshold) {
553 boost::optional<std::string>
const& rewardModelName,
555 std::shared_ptr<storm::logic::Formula const>
const& subformula) {
558 STORM_LOG_ASSERT(!rewardModelName,
"Probability operator with reward information parsed");
559 return createProbabilityOperatorFormula(operatorInformation, subformula);
561 return createRewardOperatorFormula(rewardModelName, operatorInformation, subformula);
563 STORM_LOG_ASSERT(!rewardModelName,
"LRA operator with reward information parsed");
564 return createLongRunAverageOperatorFormula(operatorInformation, subformula);
566 STORM_LOG_ASSERT(!rewardModelName,
"Time operator with reward model name parsed");
567 return createTimeOperatorFormula(operatorInformation, subformula);
569 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Unexpected formula context.");
573std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createLongRunAverageOperatorFormula(
578std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createRewardOperatorFormula(
580 std::shared_ptr<storm::logic::Formula const>
const& subformula)
const {
584std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createTimeOperatorFormula(
589std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createProbabilityOperatorFormula(
594std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBinaryBooleanStateFormula(
595 std::shared_ptr<storm::logic::Formula const>
const& leftSubformula, std::shared_ptr<storm::logic::Formula const>
const& rightSubformula,
600std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUnaryBooleanStateFormula(
601 std::shared_ptr<storm::logic::Formula const>
const& subformula, boost::optional<storm::logic::UnaryBooleanStateFormula::OperatorType>
const& operatorType) {
609std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBinaryBooleanPathFormula(
610 std::shared_ptr<storm::logic::Formula const>
const& leftSubformula, std::shared_ptr<storm::logic::Formula const>
const& rightSubformula,
615std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUnaryBooleanPathFormula(
616 std::shared_ptr<storm::logic::Formula const>
const& subformula, boost::optional<storm::logic::UnaryBooleanPathFormula::OperatorType>
const& operatorType) {
624std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBinaryBooleanStateOrPathFormula(
625 std::shared_ptr<storm::logic::Formula const>
const& leftSubformula, std::shared_ptr<storm::logic::Formula const>
const& rightSubformula,
627 if (leftSubformula->isStateFormula() && rightSubformula->isStateFormula()) {
628 return createBinaryBooleanStateFormula(leftSubformula, rightSubformula, operatorType);
629 }
else if (leftSubformula->isPathFormula() || rightSubformula->isPathFormula()) {
630 return createBinaryBooleanPathFormula(leftSubformula, rightSubformula, operatorType);
632 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Subformulas have unexpected type.");
635std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUnaryBooleanStateOrPathFormula(
636 std::shared_ptr<storm::logic::Formula const>
const& subformula, boost::optional<storm::logic::UnaryBooleanOperatorType>
const& operatorType) {
637 if (subformula->isStateFormula()) {
638 return createUnaryBooleanStateFormula(subformula, operatorType);
639 }
else if (subformula->isPathFormula()) {
640 return createUnaryBooleanPathFormula(subformula, operatorType);
642 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Subformulas have unexpected type.");
645bool FormulaParserGrammar::isValidMultiBoundedPathFormulaOperand(std::shared_ptr<storm::logic::Formula const>
const& operand) {
646 if (operand->isBoundedUntilFormula()) {
647 if (!operand->asBoundedUntilFormula().isMultiDimensional()) {
650 STORM_LOG_ERROR(
"Composition of multidimensional bounded until formula must consist of single dimension subformulas. Got '" << *operand
656std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createMultiBoundedPathFormula(
657 std::vector<std::shared_ptr<storm::logic::Formula const>>
const& subformulas) {
658 std::vector<std::shared_ptr<storm::logic::Formula const>> leftSubformulas, rightSubformulas;
659 std::vector<boost::optional<storm::logic::TimeBound>> lowerBounds, upperBounds;
660 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
661 for (
auto const& subformula : subformulas) {
662 STORM_LOG_THROW(subformula->isBoundedUntilFormula(), storm::exceptions::WrongFormatException,
663 "multi-path formulas require bounded until (or eventually) subformulae. Got '" << *subformula <<
"' instead.");
664 auto const& f = subformula->asBoundedUntilFormula();
665 STORM_LOG_THROW(!f.isMultiDimensional(), storm::exceptions::WrongFormatException,
666 "Composition of multidimensional bounded until formula must consist of single dimension subformulas. Got '" << f <<
"' instead.");
667 leftSubformulas.push_back(f.getLeftSubformula().asSharedPointer());
668 rightSubformulas.push_back(f.getRightSubformula().asSharedPointer());
669 if (f.hasLowerBound()) {
672 lowerBounds.emplace_back();
674 if (f.hasUpperBound()) {
677 upperBounds.emplace_back();
679 timeBoundReferences.push_back(f.getTimeBoundReference());
681 return std::shared_ptr<storm::logic::Formula const>(
685std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createMultiOperatorFormula(
690storm::expressions::Variable FormulaParserGrammar::createQuantileBoundVariables(boost::optional<storm::solver::OptimizationDirection>
const& dir,
691 std::string
const& variableName) {
692 STORM_LOG_ASSERT(manager,
"Mutable expression manager required to define quantile bound variable.");
694 if (manager->hasVariable(variableName)) {
695 var = manager->getVariable(variableName);
696 STORM_LOG_THROW(quantileFormulaVariables.count(var) > 0, storm::exceptions::WrongFormatException,
697 "Invalid quantile variable name '" << variableName <<
"' in quantile formula: variable already exists.");
699 var = manager->declareRationalVariable(variableName);
700 quantileFormulaVariables.insert(var);
703 << dir.get() <<
"' for quantile variable " << variableName
704 <<
" is ignored. This information will be derived from the subformula of the quantile.");
709std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createQuantileFormula(std::vector<storm::expressions::Variable>
const& boundVariables,
710 std::shared_ptr<storm::logic::Formula const>
const& subformula) {
714std::set<storm::expressions::Variable> FormulaParserGrammar::getUndefinedConstants(std::shared_ptr<storm::logic::Formula const>
const& formula)
const {
715 std::set<storm::expressions::Variable> result;
716 std::set<storm::expressions::Variable> usedVariables = formula->getUsedVariables();
717 std::set_intersection(usedVariables.begin(), usedVariables.end(), undefinedConstants.begin(), undefinedConstants.end(),
718 std::inserter(result, result.begin()));
723 std::shared_ptr<storm::logic::Formula const>
const& formula,
724 std::shared_ptr<storm::logic::Formula const>
const& states) {
729 return storm::jani::Property(propertyName.get(), filterExpression, this->getUndefinedConstants(formula));
731 return storm::jani::Property(std::to_string(propertyCount - 1), filterExpression, this->getUndefinedConstants(formula));
735storm::jani::Property FormulaParserGrammar::createPropertyWithDefaultFilterTypeAndStates(boost::optional<std::string>
const& propertyName,
736 std::shared_ptr<storm::logic::Formula const>
const& formula) {
741 return storm::jani::Property(std::to_string(propertyCount), formula, this->getUndefinedConstants(formula));
746 std::vector<std::variant<std::string, storm::storage::PlayerIndex>>
const& playerIds)
const {
751 std::shared_ptr<storm::logic::Formula const>
const& subformula)
const {
755bool FormulaParserGrammar::isBooleanReturnType(std::shared_ptr<storm::logic::Formula const>
const& formula,
bool raiseErrorMessage) {
756 if (formula->hasQualitativeResult()) {
759 STORM_LOG_ERROR_COND(!raiseErrorMessage,
"Formula " << *formula <<
" does not have a Boolean return type.");
763bool FormulaParserGrammar::raiseAmbiguousNonAssociativeOperatorError(std::shared_ptr<storm::logic::Formula const>
const& formula, std::string
const& op) {
764 STORM_LOG_ERROR(
"Ambiguous use of non-associative operator '" << op <<
"' in formula '" << *formula <<
" U ... '");
bool evaluateAsBool(Valuation const *valuation=nullptr) const
Evaluates the expression under the valuation of variables given by the valuation and returns the resu...
bool hasBooleanType() const
Retrieves whether the expression has a boolean return type.
bool isLiteral() const
Retrieves whether the expression is a literal.
std::string toString() const
Converts the expression into a string.
void setIdentifierMapping(qi::symbols< char, storm::expressions::Expression > const *identifiers_)
Sets an identifier mapping that is used to determine valid variables in the expression.
#define STORM_LOG_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_ERROR_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
BinaryBooleanOperatorType