171 lines
7.8 KiB
171 lines
7.8 KiB
#ifndef STORM_MONOTONICITYHELPER_H
|
|
#define STORM_MONOTONICITYHELPER_H
|
|
|
|
#include <map>
|
|
#include "Order.h"
|
|
#include "LocalMonotonicityResult.h"
|
|
#include "OrderExtender.h"
|
|
#include "AssumptionMaker.h"
|
|
#include "MonotonicityResult.h"
|
|
|
|
|
|
#include "storm/logic/Formula.h"
|
|
|
|
#include "storm/models/ModelBase.h"
|
|
#include "storm/models/sparse/Dtmc.h"
|
|
#include "storm/models/sparse/Mdp.h"
|
|
|
|
#include "storm/solver/Z3SmtSolver.h"
|
|
|
|
#include "storm/storage/SparseMatrix.h"
|
|
#include "storm/storage/expressions/BinaryRelationExpression.h"
|
|
#include "storm/storage/expressions/ExpressionManager.h"
|
|
#include "storm/storage/expressions/RationalFunctionToExpression.h"
|
|
|
|
#include "storm/utility/constants.h"
|
|
|
|
#include "storm-pars/api/region.h"
|
|
|
|
namespace storm {
|
|
namespace analysis {
|
|
|
|
template <typename ValueType, typename ConstantType>
|
|
class MonotonicityHelper {
|
|
|
|
public:
|
|
typedef typename utility::parametric::VariableType<ValueType>::type VariableType;
|
|
typedef typename utility::parametric::CoefficientType<ValueType>::type CoefficientType;
|
|
typedef typename MonotonicityResult<VariableType>::Monotonicity Monotonicity;
|
|
typedef typename storage::ParameterRegion<ValueType> Region;
|
|
|
|
/*!
|
|
* Constructor of MonotonicityHelper.
|
|
*
|
|
* @param model The model considered.
|
|
* @param formulas The formulas considered.
|
|
* @param regions The regions to consider.
|
|
* @param numberOfSamples Number of samples taken for monotonicity checking, default 0,
|
|
* if 0 then no check on samples is executed.
|
|
* @param precision Precision on which the samples are compared
|
|
* @param dotOutput Whether or not dot output should be generated for the ROs.
|
|
*/
|
|
MonotonicityHelper(std::shared_ptr<models::sparse::Model<ValueType>> model, std::vector<std::shared_ptr<logic::Formula const>> formulas, std::vector<storage::ParameterRegion<ValueType>> regions, uint_fast64_t numberOfSamples=0, double const& precision=0.000001, bool dotOutput = false);
|
|
|
|
/*!
|
|
* Checks if a derivative >=0 or/and <=0
|
|
*
|
|
* @param derivative The derivative you want to check
|
|
* @return pair of bools, >= 0 and <= 0
|
|
*/
|
|
static std::pair<bool, bool> checkDerivative(ValueType derivative, storage::ParameterRegion<ValueType> reg) {
|
|
bool monIncr = false;
|
|
bool monDecr = false;
|
|
|
|
if (derivative.isZero()) {
|
|
monIncr = true;
|
|
monDecr = true;
|
|
} else if (derivative.isConstant()) {
|
|
monIncr = derivative.constantPart() >= 0;
|
|
monDecr = derivative.constantPart() <= 0;
|
|
} else {
|
|
|
|
std::shared_ptr<utility::solver::SmtSolverFactory> smtSolverFactory = std::make_shared<utility::solver::MathsatSmtSolverFactory>();
|
|
std::shared_ptr<expressions::ExpressionManager> manager(new expressions::ExpressionManager());
|
|
solver::Z3SmtSolver s(*manager);
|
|
std::set<VariableType> variables = derivative.gatherVariables();
|
|
|
|
expressions::Expression exprBounds = manager->boolean(true);
|
|
for (auto variable : variables) {
|
|
auto managerVariable = manager->declareRationalVariable(variable.name());
|
|
auto lb = utility::convertNumber<RationalNumber>(reg.getLowerBoundary(variable));
|
|
auto ub = utility::convertNumber<RationalNumber>(reg.getUpperBoundary(variable));
|
|
exprBounds = exprBounds && manager->rational(lb) < managerVariable && managerVariable < manager->rational(ub);
|
|
}
|
|
|
|
auto converter = expressions::RationalFunctionToExpression<ValueType>(manager);
|
|
|
|
// < 0, so not monotone increasing. If this is unsat, then it should be monotone increasing.
|
|
expressions::Expression exprToCheck = converter.toExpression(derivative) < manager->rational(0);
|
|
s.add(exprBounds);
|
|
s.add(exprToCheck);
|
|
monIncr = s.check() == solver::SmtSolver::CheckResult::Unsat;
|
|
|
|
// > 0, so not monotone decreasing. If this is unsat it should be monotone decreasing.
|
|
exprToCheck = converter.toExpression(derivative) > manager->rational(0);
|
|
s.reset();
|
|
s.add(exprBounds);
|
|
s.add(exprToCheck);
|
|
monDecr = s.check() == solver::SmtSolver::CheckResult::Unsat;
|
|
}
|
|
assert (!(monIncr && monDecr) || derivative.isZero());
|
|
|
|
return std::pair<bool, bool>(monIncr, monDecr);
|
|
}
|
|
|
|
/*!
|
|
* Builds Reachability Orders for the given model and simultaneously uses them to check for Monotonicity.
|
|
*
|
|
* @param outfile Outfile to which results are written.
|
|
* @param dotOutfileName Name for the files of the dot outputs should they be generated
|
|
* @return Map which maps each order to its Reachability Order and used assumptions.
|
|
*/
|
|
std::map<std::shared_ptr<Order>, std::pair<std::shared_ptr<MonotonicityResult<VariableType>>, std::vector<std::shared_ptr<expressions::BinaryRelationExpression>>>> checkMonotonicityInBuild(std::ostream& outfile, bool usePLA = false, std::string dotOutfileName = "dotOutput");
|
|
|
|
/*!
|
|
* Checks for local monotonicity at the given state.
|
|
*
|
|
* @param order the order on which the monotonicity should be checked
|
|
* @param state the considerd state
|
|
* @param var the variable in which we check for monotonicity
|
|
* @param region the region on which we check the monotonicity
|
|
* @return Incr, Decr, Constant, Unknown or Not
|
|
*/
|
|
Monotonicity checkLocalMonotonicity(std::shared_ptr<Order> order, uint_fast64_t state, VariableType var, storage::ParameterRegion<ValueType> region);
|
|
|
|
private:
|
|
void createOrder();
|
|
|
|
void checkMonotonicityOnSamples(std::shared_ptr<models::sparse::Dtmc<ValueType>> model, uint_fast64_t numberOfSamples);
|
|
|
|
void checkMonotonicityOnSamples(std::shared_ptr<models::sparse::Mdp<ValueType>> model, uint_fast64_t numberOfSamples);
|
|
|
|
void extendOrderWithAssumptions(std::shared_ptr<Order> order, uint_fast64_t val1, uint_fast64_t val2, std::vector<std::shared_ptr<expressions::BinaryRelationExpression>> assumptions, std::shared_ptr<MonotonicityResult<VariableType>> monRes);
|
|
|
|
Monotonicity checkTransitionMonRes(ValueType function, VariableType param, Region region);
|
|
|
|
ValueType getDerivative(ValueType function, VariableType var);
|
|
|
|
|
|
std::shared_ptr<models::ModelBase> model;
|
|
|
|
std::vector<std::shared_ptr<logic::Formula const>> formulas;
|
|
|
|
bool dotOutput;
|
|
|
|
bool checkSamples;
|
|
|
|
bool onlyCheckOnOrder;
|
|
|
|
MonotonicityResult<VariableType> resultCheckOnSamples;
|
|
|
|
std::map<VariableType, std::vector<uint_fast64_t>> occuringStatesAtVariable;
|
|
|
|
std::map<std::shared_ptr<Order>, std::pair<std::shared_ptr<MonotonicityResult<VariableType>>, std::vector<std::shared_ptr<expressions::BinaryRelationExpression>>>> monResults;
|
|
|
|
OrderExtender<ValueType, ConstantType> *extender;
|
|
|
|
ConstantType precision;
|
|
|
|
Region region;
|
|
|
|
storage::SparseMatrix<ValueType> matrix;
|
|
|
|
std::unordered_map<ValueType, std::unordered_map<VariableType, ValueType>> derivatives;
|
|
|
|
AssumptionMaker<ValueType, ConstantType> assumptionMaker;
|
|
|
|
|
|
};
|
|
}
|
|
}
|
|
#endif //STORM_MONOTONICITYHELPER_H
|