101 lines
5.9 KiB

#include "storm/builder/TerminalStatesGetter.h"
#include "storm/storage/expressions/Expression.h"
#include "storm/logic/Formulas.h"
namespace storm {
namespace builder {
void getTerminalStatesFromFormula(storm::logic::Formula const& formula, std::function<void(storm::expressions::Expression const&, bool)> const& terminalExpressionCallback, std::function<void(std::string const&, bool)> const& terminalLabelCallback) {
if (formula.isAtomicExpressionFormula()) {
terminalExpressionCallback(formula.asAtomicExpressionFormula().getExpression(), true);
} else if (formula.isAtomicLabelFormula()) {
terminalLabelCallback(formula.asAtomicLabelFormula().getLabel(), true);
} else if (formula.isEventuallyFormula()) {
storm::logic::Formula const& sub = formula.asEventuallyFormula().getSubformula();
if (sub.isAtomicExpressionFormula() || sub.isAtomicLabelFormula()) {
getTerminalStatesFromFormula(sub, terminalExpressionCallback, terminalLabelCallback);
}
} else if (formula.isUntilFormula()) {
storm::logic::Formula const& right = formula.asUntilFormula().getRightSubformula();
if (right.isAtomicExpressionFormula() || right.isAtomicLabelFormula()) {
getTerminalStatesFromFormula(right, terminalExpressionCallback, terminalLabelCallback);
}
storm::logic::Formula const& left = formula.asUntilFormula().getLeftSubformula();
if (left.isAtomicExpressionFormula()) {
terminalExpressionCallback(left.asAtomicExpressionFormula().getExpression(), false);
} else if (left.isAtomicLabelFormula()) {
terminalLabelCallback(left.asAtomicLabelFormula().getLabel(), false);
}
} else if (formula.isBoundedUntilFormula()) {
storm::logic::BoundedUntilFormula const& boundedUntil = formula.asBoundedUntilFormula();
bool hasLowerBound = false;
for (uint64_t i = 0; i < boundedUntil.getDimension(); ++i) {
if (boundedUntil.hasLowerBound(i) && (boundedUntil.getLowerBound(i).containsVariables() || !storm::utility::isZero(boundedUntil.getLowerBound(i).evaluateAsRational()))) {
hasLowerBound = true;
break;
}
}
if (!hasLowerBound) {
storm::logic::Formula const& right = boundedUntil.getRightSubformula();
if (right.isAtomicExpressionFormula() || right.isAtomicLabelFormula()) {
getTerminalStatesFromFormula(right, terminalExpressionCallback, terminalLabelCallback);
}
}
storm::logic::Formula const& left = boundedUntil.getLeftSubformula();
if (left.isAtomicExpressionFormula()) {
terminalExpressionCallback(left.asAtomicExpressionFormula().getExpression(), false);
} else if (left.isAtomicLabelFormula()) {
terminalLabelCallback(left.asAtomicLabelFormula().getLabel(), false);
}
} else if (formula.isProbabilityOperatorFormula()) {
storm::logic::Formula const& sub = formula.asProbabilityOperatorFormula().getSubformula();
if (sub.isEventuallyFormula() || sub.isUntilFormula() || sub.isBoundedUntilFormula()) {
getTerminalStatesFromFormula(sub, terminalExpressionCallback, terminalLabelCallback);
}
} else if (formula.isRewardOperatorFormula() || formula.isTimeOperatorFormula()) {
storm::logic::Formula const& sub = formula.asOperatorFormula().getSubformula();
if (sub.isEventuallyFormula()) {
getTerminalStatesFromFormula(sub, terminalExpressionCallback, terminalLabelCallback);
}
}
}
void TerminalStates::clear() {
terminalExpressions.clear();
negatedTerminalExpressions.clear();
terminalLabels.clear();
negatedTerminalLabels.clear();
}
bool TerminalStates::empty() const {
return terminalExpressions.empty() && negatedTerminalExpressions.empty() && terminalLabels.empty() && negatedTerminalLabels.empty();
}
storm::expressions::Expression TerminalStates::asExpression(std::function<storm::expressions::Expression(std::string const&)> const& labelToExpressionMap) const {
auto allTerminalExpressions = terminalExpressions;
for (auto const& e : negatedTerminalExpressions) {
allTerminalExpressions.push_back(!e);
}
for (auto const& l : terminalLabels) {
allTerminalExpressions.push_back(labelToExpressionMap(l));
}
for (auto const& l : negatedTerminalLabels) {
allTerminalExpressions.push_back(!labelToExpressionMap(l));
}
STORM_LOG_ASSERT(!allTerminalExpressions.empty(), "Unable to convert empty terminal state set to expression");
return storm::expressions::disjunction(allTerminalExpressions);
}
TerminalStates getTerminalStatesFromFormula(storm::logic::Formula const& formula) {
TerminalStates result;
getTerminalStatesFromFormula(formula, [&result](storm::expressions::Expression const& expr, bool inverted){ if(inverted) { result.terminalExpressions.push_back(expr);} else {result.negatedTerminalExpressions.push_back(expr);} },
[&result](std::string const& label, bool inverted){ if(inverted) { result.terminalLabels.push_back(label);} else {result.negatedTerminalLabels.push_back(label);} });
return result;
}
}
}