Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
GraphConditions.cpp
Go to the documentation of this file.
2
11
12namespace storm {
13namespace analysis {
14
15namespace {
16
20template<typename PolynomialType>
21storm::expressions::Expression toExpression(PolynomialType const& polynomial, std::shared_ptr<storm::expressions::ExpressionManager> const& manager) {
22 return storm::expressions::polynomialToExpression(polynomial, manager);
23}
24
25} // namespace
26
28 : expressionManager(std::make_shared<storm::expressions::ExpressionManager>()) {
29 process(model);
30}
31
33 return this->wellformedConstraintSet;
34}
35
37 return this->graphPreservingConstraintSet;
38}
39
40std::set<storm::RationalFunctionVariable> const& ConstraintCollector::getVariables() const {
41 return this->variableSet;
42}
43
44storm::expressions::Expression ConstraintCollector::relateToZero(storm::RawPolynomial const& polynomial, storm::expressions::RelationType relation) const {
45 auto zero = expressionManager->rational(storm::utility::zero<storm::RationalNumber>());
46 switch (relation) {
48 return toExpression(polynomial, expressionManager) < zero;
50 return toExpression(polynomial, expressionManager) <= zero;
52 return toExpression(-polynomial, expressionManager) < zero;
54 return toExpression(-polynomial, expressionManager) <= zero;
56 return toExpression(polynomial, expressionManager) == zero;
58 return toExpression(polynomial, expressionManager) != zero;
59 }
60 STORM_LOG_THROW_UNCONDITIONALLY(storm::exceptions::UnexpectedException, "Unhandled relation.");
61}
62
63bool ConstraintCollector::addConstraint(ConstraintSet& constraintSet, ConstraintIndex& constraintIndex, storm::expressions::Expression const& constraint) {
64 auto& candidates = constraintIndex[hashVisitor.hash(constraint)];
65 for (auto const& candidate : candidates) {
66 if (candidate.isSyntacticallyEqual(constraint)) {
67 return false;
68 }
69 }
70 candidates.push_back(constraint);
71 constraintSet.push_back(constraint);
72 return true;
73}
74
75void ConstraintCollector::wellformedRequiresNonNegativeEntries(storm::RationalFunction const& value) {
76 if (storm::utility::isConstant(value)) {
77 // A constant entry does not involve any parameter, so it does not restrict the parameter region. A constant
78 // that violates the bound, however, makes the well-formedness constraints unsatisfiable, which we express
79 // by a trivially false constraint.
81 addConstraint(wellformedConstraintSet, wellformedConstraintIndex, expressionManager->boolean(false));
82 }
83 return;
84 }
85
86 auto valueVariables = value.gatherVariables();
87 variableSet.insert(valueVariables.begin(), valueVariables.end());
88
89 storm::RawPolynomial nominator = value.nominator().polynomialWithCoefficient();
90 storm::RawPolynomial denominator = value.denominator().polynomialWithCoefficient();
91
92 if (denominator.isConstant()) {
93 // The sign of the denominator is known, so non-negativity of the quotient reduces to a sign constraint on
94 // the nominator.
95 STORM_LOG_ASSERT(denominator.constantPart() != 0, "Denominator should not be zero.");
97 addConstraint(wellformedConstraintSet, wellformedConstraintIndex, relateToZero(nominator, relation));
98 } else {
99 // The denominator may change its sign, so we need to constrain that it never vanishes and that the sign of
100 // the nominator follows the sign of the denominator.
101 addConstraint(wellformedConstraintSet, wellformedConstraintIndex, relateToZero(denominator, storm::expressions::RelationType::NotEqual));
102 addConstraint(wellformedConstraintSet, wellformedConstraintIndex,
105 relateToZero(nominator, storm::expressions::RelationType::LessOrEqual)));
106 }
107}
108
109void ConstraintCollector::wellformedRequiresAtMostOne(storm::RationalFunction const& value) {
110 if (storm::utility::isConstant(value)) {
112 addConstraint(wellformedConstraintSet, wellformedConstraintIndex, expressionManager->boolean(false));
113 }
114 return;
115 }
116
117 auto denominator = value.denominator().polynomialWithCoefficient();
118 if (!denominator.isConstant()) {
119 // TODO: Assert: value <= 1 <==> if denom > 0 then nom - denom <= 0 else nom - denom >= 0
120 // This sign reasoning cannot be expressed with the relations available in the expression system.
121 return;
122 }
123
124 STORM_LOG_ASSERT(denominator.constantPart() != 0, "Denominator should not be zero.");
125 storm::RawPolynomial nominator = value.nominator().polynomialWithCoefficient();
126 // Express the bound as a relation of the difference to zero, so that it coincides with another constraint
127 // whenever the two are equivalent.
129 addConstraint(wellformedConstraintSet, wellformedConstraintIndex, relateToZero(nominator - denominator, relation));
130}
131
132void ConstraintCollector::graphPreservingRequiresNonZero(storm::RationalFunction const& value) {
133 addConstraint(graphPreservingConstraintSet, graphPreservingConstraintIndex,
134 relateToZero(value.nominator().polynomialWithCoefficient(), storm::expressions::RelationType::NotEqual));
135}
136
137void ConstraintCollector::process(storm::models::sparse::Model<storm::RationalFunction> const& model) {
138 bool const isCtmc = model.getType() == storm::models::ModelType::Ctmc;
139
140 if (!isCtmc) {
141 for (uint_fast64_t action = 0; action < model.getTransitionMatrix().getRowCount(); ++action) {
143
144 for (auto transitionIt = model.getTransitionMatrix().begin(action); transitionIt != model.getTransitionMatrix().end(action); ++transitionIt) {
145 auto const& value = transitionIt->getValue();
146 sum += value;
147 // Assert: 0 <= transition <= 1
148 wellformedRequiresNonNegativeEntries(value);
149 wellformedRequiresAtMostOne(value);
150 if (!storm::utility::isConstant(value)) {
151 // Assert: transition > 0, so that the underlying graph does not change.
152 graphPreservingRequiresNonZero(value);
153 }
154 }
155 STORM_LOG_ASSERT(!storm::utility::isConstant(sum) || storm::utility::isOne(sum), "If the sum is a constant, it must be equal to 1.");
156 if (!storm::utility::isConstant(sum)) {
157 auto sumVariables = sum.gatherVariables();
158 variableSet.insert(sumVariables.begin(), sumVariables.end());
159 // Assert: sum == 1
160 addConstraint(wellformedConstraintSet, wellformedConstraintIndex,
161 relateToZero(sum.nominator().polynomialWithCoefficient() - sum.denominator().polynomialWithCoefficient(),
163 }
164 }
165 } else {
166 for (auto const& transition : model.getTransitionMatrix()) {
167 // Assert: 0 <= transition
168 wellformedRequiresNonNegativeEntries(transition.getValue());
169 if (!storm::utility::isConstant(transition.getValue())) {
170 // Assert: transition > 0, so that the underlying graph does not change.
171 graphPreservingRequiresNonZero(transition.getValue());
172 }
173 }
174 }
175
176 if (isCtmc) {
177 auto const& exitRateVector = static_cast<storm::models::sparse::Ctmc<storm::RationalFunction> const&>(model).getExitRateVector();
178 for (auto const& exitRate : exitRateVector) {
179 wellformedRequiresNonNegativeEntries(exitRate);
180 }
182 auto const& exitRateVector = static_cast<storm::models::sparse::MarkovAutomaton<storm::RationalFunction> const&>(model).getExitRates();
183 for (auto const& exitRate : exitRateVector) {
184 wellformedRequiresNonNegativeEntries(exitRate);
185 }
186 }
187
188 for (auto const& rewModelEntry : model.getRewardModels()) {
189 if (rewModelEntry.second.hasStateRewards()) {
190 for (auto const& stateReward : rewModelEntry.second.getStateRewardVector()) {
191 wellformedRequiresNonNegativeEntries(stateReward);
192 }
193 }
194 if (rewModelEntry.second.hasStateActionRewards()) {
195 for (auto const& stateActionReward : rewModelEntry.second.getStateActionRewardVector()) {
196 wellformedRequiresNonNegativeEntries(stateActionReward);
197 }
198 }
199 if (rewModelEntry.second.hasTransitionRewards()) {
200 for (auto const& entry : rewModelEntry.second.getTransitionRewardMatrix()) {
201 wellformedRequiresNonNegativeEntries(entry.getValue());
202 }
203 }
204 }
205}
206
210
211} // namespace analysis
212} // namespace storm
ConstraintSet const & getGraphPreservingConstraints() const
Returns the set of graph-preserving constraints.
std::set< storm::RationalFunctionVariable > const & getVariables() const
Returns the set of variables in the model.
ConstraintCollector(storm::models::sparse::Model< storm::RationalFunction > const &model)
Constructs a constraint collector for the given model.
void operator()(storm::models::sparse::Model< storm::RationalFunction > const &model)
Constructs the constraints for the given model by calling the process method.
ConstraintSet const & getWellformedConstraints() const
Returns the set of wellformed-ness constraints.
std::vector< storm::expressions::Expression > ConstraintSet
The type of the collected constraints.
void gatherVariables(std::set< storm::expressions::Variable > &variables) const
Retrieves the set of all variables that appear in the expression.
std::size_t hash(storm::expressions::Expression const &expression)
Computes the hash of the given expression.
virtual ModelType getType() const
Return the actual type of the model.
Definition ModelBase.cpp:7
Base class for all sparse models.
Definition Model.h:34
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:226
std::unordered_map< std::string, RewardModelType > const & getRewardModels() const
Retrieves the reward models.
Definition Model.cpp:728
#define STORM_LOG_THROW_UNCONDITIONALLY(exception, message)
Definition macros.h:48
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
Expression sum(std::vector< storm::expressions::Expression > const &expressions)
RelationType
An enum type specifying the different relations applicable.
Expression polynomialToExpression(PolynomialType const &polynomial, std::shared_ptr< ExpressionManager > const &manager)
Converts the given polynomial into a Storm expression.
bool isOne(ValueType const &a)
Definition constants.cpp:39
NumberTraits< RationalType >::IntegerType denominator(RationalType const &number)
bool isConstant(ValueType const &)
ValueType zero()
Definition constants.cpp:26
ValueType one()
Definition constants.cpp:21
carl::RationalFunction< Polynomial, true > RationalFunction
carl::MultivariatePolynomial< RationalFunctionCoefficient > RawPolynomial
void process()