|
|
@ -17,6 +17,10 @@ |
|
|
|
|
|
|
|
#include "storm/modelchecker/results/CheckResult.h"
|
|
|
|
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
|
|
#include "storm/solver/Z3SmtSolver.h"
|
|
|
|
#include "storm/storage/expressions/ExpressionManager.h"
|
|
|
|
|
|
|
|
#include "storm/storage/expressions/RationalFunctionToExpression.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace storm { |
|
|
@ -108,7 +112,7 @@ namespace storm { |
|
|
|
outfile << "X " << itr2->first; |
|
|
|
} else { |
|
|
|
if (itr2->second.first && itr2->second.second) { |
|
|
|
STORM_PRINT(" - Constant in" << itr2->first); |
|
|
|
STORM_PRINT(" - Constant in" << itr2->first << std::endl); |
|
|
|
outfile << "C " << itr2->first; |
|
|
|
} else if (itr2->second.first) { |
|
|
|
STORM_PRINT(" - Monotone increasing in: " << itr2->first << std::endl); |
|
|
@ -294,22 +298,31 @@ namespace storm { |
|
|
|
|
|
|
|
for (auto itr2 = transitions.begin(); itr2 != transitions.end(); ++itr2) { |
|
|
|
for (auto itr3 = transitions.begin(); itr3 != transitions.end(); ++itr3) { |
|
|
|
auto derivative2 = (*itr2).second.derivative(*itr); |
|
|
|
auto derivative3 = (*itr3).second.derivative(*itr); |
|
|
|
STORM_LOG_THROW(derivative2.isConstant() && derivative3.isConstant(), |
|
|
|
storm::exceptions::NotSupportedException, |
|
|
|
"Expecting derivative to be constant"); |
|
|
|
auto derivative2 = itr2->second.derivative(*itr); |
|
|
|
auto derivative3 = itr3->second.derivative(*itr); |
|
|
|
|
|
|
|
auto compare = lattice->compare((*itr2).first, (*itr3).first); |
|
|
|
auto compare = lattice->compare(itr2->first, itr3->first); |
|
|
|
|
|
|
|
if (compare == storm::analysis::Lattice::ABOVE) { |
|
|
|
// As the first state (itr2) is above the second state (itr3) it is sufficient to look at the derivative of itr2.
|
|
|
|
value->first &= derivative2.constantPart() >= 0; |
|
|
|
value->second &= derivative2.constantPart() <= 0; |
|
|
|
std::pair<bool,bool> mon2; |
|
|
|
if (derivative2.isConstant()) { |
|
|
|
mon2 = std::pair<bool,bool>(derivative2.constantPart() >= 0, derivative2.constantPart() <=0); |
|
|
|
} else { |
|
|
|
mon2 = checkDerivative(derivative2); |
|
|
|
} |
|
|
|
value->first &= mon2.first; |
|
|
|
value->second &= mon2.second; |
|
|
|
} else if (compare == storm::analysis::Lattice::BELOW) { |
|
|
|
// As the second state (itr3) is above the first state (itr2) it is sufficient to look at the derivative of itr3.
|
|
|
|
value->first &= derivative3.constantPart() >= 0; |
|
|
|
value->second &= derivative3.constantPart() <= 0; |
|
|
|
std::pair<bool,bool> mon3; |
|
|
|
if (derivative2.isConstant()) { |
|
|
|
mon3 = std::pair<bool,bool>(derivative3.constantPart() >= 0, derivative3.constantPart() <=0); |
|
|
|
} else { |
|
|
|
mon3 = checkDerivative(derivative3); |
|
|
|
} |
|
|
|
value->first &= mon3.first; |
|
|
|
value->second &= mon3.second; |
|
|
|
} else if (compare == storm::analysis::Lattice::SAME) { |
|
|
|
// TODO: klopt dit
|
|
|
|
// Behaviour doesn't matter, as the states are at the same level.
|
|
|
@ -331,6 +344,51 @@ namespace storm { |
|
|
|
return varsMonotone; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename ValueType> |
|
|
|
std::pair<bool, bool> MonotonicityChecker<ValueType>::checkDerivative(ValueType derivative) { |
|
|
|
bool monIncr = false; |
|
|
|
bool monDecr = false; |
|
|
|
|
|
|
|
std::shared_ptr<storm::utility::solver::SmtSolverFactory> smtSolverFactory = std::make_shared<storm::utility::solver::MathsatSmtSolverFactory>(); |
|
|
|
std::shared_ptr<storm::expressions::ExpressionManager> manager( |
|
|
|
new storm::expressions::ExpressionManager()); |
|
|
|
|
|
|
|
storm::solver::Z3SmtSolver s(*manager); |
|
|
|
storm::solver::SmtSolver::CheckResult smtResult = storm::solver::SmtSolver::CheckResult::Unknown; |
|
|
|
|
|
|
|
std::set<carl::Variable> variables = derivative.gatherVariables(); |
|
|
|
|
|
|
|
|
|
|
|
for (auto variable : variables) { |
|
|
|
manager->declareRationalVariable(variable.name()); |
|
|
|
|
|
|
|
} |
|
|
|
storm::expressions::Expression exprBounds = manager->boolean(true); |
|
|
|
auto managervars = manager->getVariables(); |
|
|
|
for (auto var : managervars) { |
|
|
|
exprBounds = exprBounds && manager->rational(0) <= var && manager->rational(1) >= var; |
|
|
|
} |
|
|
|
|
|
|
|
auto converter = storm::expressions::RationalFunctionToExpression<ValueType>(manager); |
|
|
|
|
|
|
|
storm::expressions::Expression exprToCheck1 = converter.toExpression(derivative) >= manager->rational(0); |
|
|
|
s.add(exprBounds); |
|
|
|
s.add(exprToCheck1); |
|
|
|
smtResult = s.check(); |
|
|
|
monIncr = smtResult == storm::solver::SmtSolver::CheckResult::Sat; |
|
|
|
|
|
|
|
storm::expressions::Expression exprToCheck2 = converter.toExpression(derivative) <= manager->rational(0); |
|
|
|
s.reset(); |
|
|
|
smtResult = storm::solver::SmtSolver::CheckResult::Unknown; |
|
|
|
s.add(exprBounds); |
|
|
|
s.add(exprToCheck2); |
|
|
|
smtResult = s.check(); |
|
|
|
monDecr = smtResult == storm::solver::SmtSolver::CheckResult::Sat; |
|
|
|
|
|
|
|
return std::pair<bool, bool>(monIncr, monDecr); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename ValueType> |
|
|
|
bool MonotonicityChecker<ValueType>::somewhereMonotonicity(storm::analysis::Lattice* lattice) { |
|
|
|
std::shared_ptr<storm::models::sparse::Model<ValueType>> sparseModel = model->as<storm::models::sparse::Model<ValueType>>(); |
|
|
@ -359,26 +417,36 @@ namespace storm { |
|
|
|
} |
|
|
|
std::pair<bool, bool> *value = &varsMonotone.find(*itr)->second; |
|
|
|
std::pair<bool, bool> old = *value; |
|
|
|
|
|
|
|
// TODO deze ook aanpassen aan deel met smt solver
|
|
|
|
for (auto itr2 = transitions.begin(); itr2 != transitions.end(); ++itr2) { |
|
|
|
for (auto itr3 = transitions.begin(); itr3 != transitions.end(); ++itr3) { |
|
|
|
auto derivative2 = (*itr2).second.derivative(*itr); |
|
|
|
auto derivative3 = (*itr3).second.derivative(*itr); |
|
|
|
STORM_LOG_THROW(derivative2.isConstant() && derivative3.isConstant(), |
|
|
|
storm::exceptions::NotSupportedException, |
|
|
|
"Expecting derivative to be constant"); |
|
|
|
auto derivative2 = itr2->second.derivative(*itr); |
|
|
|
auto derivative3 = itr3->second.derivative(*itr); |
|
|
|
|
|
|
|
auto compare = lattice->compare((*itr2).first, (*itr3).first); |
|
|
|
auto compare = lattice->compare(itr2->first, itr3->first); |
|
|
|
|
|
|
|
if (compare == storm::analysis::Lattice::ABOVE) { |
|
|
|
// As the first state (itr2) is above the second state (itr3) it is sufficient to look at the derivative of itr2.
|
|
|
|
value->first &= derivative2.constantPart() >= 0; |
|
|
|
value->second &= derivative2.constantPart() <= 0; |
|
|
|
std::pair<bool,bool> mon2; |
|
|
|
if (derivative2.isConstant()) { |
|
|
|
mon2 = std::pair<bool,bool>(derivative2.constantPart() >= 0, derivative2.constantPart() <=0); |
|
|
|
} else { |
|
|
|
mon2 = checkDerivative(derivative2); |
|
|
|
} |
|
|
|
value->first &= mon2.first; |
|
|
|
value->second &= mon2.second; |
|
|
|
} else if (compare == storm::analysis::Lattice::BELOW) { |
|
|
|
// As the second state (itr3) is above the first state (itr2) it is sufficient to look at the derivative of itr3.
|
|
|
|
value->first &= derivative3.constantPart() >= 0; |
|
|
|
value->second &= derivative3.constantPart() <= 0; |
|
|
|
std::pair<bool,bool> mon3; |
|
|
|
if (derivative2.isConstant()) { |
|
|
|
mon3 = std::pair<bool,bool>(derivative3.constantPart() >= 0, derivative3.constantPart() <=0); |
|
|
|
} else { |
|
|
|
mon3 = checkDerivative(derivative3); |
|
|
|
} |
|
|
|
value->first &= mon3.first; |
|
|
|
value->second &= mon3.second; |
|
|
|
} else if (compare == storm::analysis::Lattice::SAME) { |
|
|
|
// TODO: klopt dit
|
|
|
|
// Behaviour doesn't matter, as the states are at the same level.
|
|
|
|
} else { |
|
|
|
// As the relation between the states is unknown, we don't do anything
|
|
|
|