Browse Source

Added correction of constraint for non-Markovian states

and better lower bound computation
tempestpy_adaptions
Alexander Bork 6 years ago
parent
commit
0baccee440
  1. 58
      src/storm-dft/modelchecker/dft/DFTASFChecker.cpp
  2. 13
      src/storm-dft/modelchecker/dft/DFTASFChecker.h
  3. 33
      src/storm-dft/modelchecker/dft/SmtConstraint.cpp

58
src/storm-dft/modelchecker/dft/DFTASFChecker.cpp

@ -325,6 +325,7 @@ namespace storm {
void DFTASFChecker::addMarkovianConstraints() {
uint64_t nrMarkovian = dft.nrBasicElements();
std::set<size_t> depElements;
// Vector containing (non-)Markovian constraints for each timepoint
std::vector<std::vector<std::shared_ptr<SmtConstraint>>> markovianC(nrMarkovian);
std::vector<std::vector<std::shared_ptr<SmtConstraint>>> nonMarkovianC(nrMarkovian);
@ -352,13 +353,14 @@ namespace storm {
constraints.back()->setDescription("Markovian (" + std::to_string(i) + ") iff all dependent events which trigger failed also failed.");
}
// In non-Markovian steps the next failed element is a dependent BE (constraint 10)
// In non-Markovian steps the next failed element is a dependent BE (constraint 10) + additions to specification in paper
for (size_t j = 0; j < dft.nrElements(); ++j) {
std::shared_ptr<storm::storage::DFTElement<ValueType> const> element = dft.getElement(j);
if (element->isBasicElement()) {
auto be = std::static_pointer_cast<storm::storage::DFTBE<double> const>(element);
if (be->hasIngoingDependencies()) {
depElements.emplace(j);
for (uint64_t i = 0; i < nrMarkovian -1; ++i) {
std::shared_ptr<SmtConstraint> nextFailure = std::make_shared<IsConstantValue>(
timePointVariables.at(j), i + 1);
@ -372,6 +374,14 @@ namespace storm {
}
}
for (uint64_t i = 0; i < nrMarkovian; ++i) {
std::vector<std::shared_ptr<SmtConstraint>> dependentConstr;
for (auto dependentEvent: depElements) {
std::shared_ptr<SmtConstraint> nextFailure = std::make_shared<IsConstantValue>(
timePointVariables.at(dependentEvent), i + 1);
dependentConstr.push_back(nextFailure);
}
// Add Constraint that any DEPENDENT event has to fail next
nonMarkovianC[i].push_back(std::make_shared<Or>(dependentConstr));
constraints.push_back(std::make_shared<Implies>(std::make_shared<IsBoolValue>(markovianVariables.at(i), false), std::make_shared<And>(nonMarkovianC[i])));
constraints.back()->setDescription("Non-Markovian (" + std::to_string(i) + ") -> next failure is dependent BE.");
}
@ -504,13 +514,47 @@ namespace storm {
return checkTleFailsWithEq(notFailed);
}
uint64_t DFTASFChecker::correctLowerBound(uint64_t bound) {
storm::solver::SmtSolver::CheckResult
DFTASFChecker::checkFailsWithLessThanMarkovianState(uint64_t checkNumber) {
STORM_LOG_ASSERT(solver, "SMT Solver was not initialized, call toSolver() before checking queries");
uint64_t nrMarkovian = dft.nrBasicElements();
std::vector<uint64_t> markovianIndices;
// Get Markovian variable indices
for (uint64_t i = 0; i < nrMarkovian; ++i) {
markovianIndices.push_back(markovianVariables.at(i));
}
// Set backtracking marker to check several properties without reconstructing DFT encoding
solver->push();
// Constraint that toplevel element can fail with less or equal 'bound' failures
std::shared_ptr<SmtConstraint> countConstr = std::make_shared<BoolCountIsLessConstant>(
markovianIndices, checkNumber);
std::shared_ptr<storm::expressions::ExpressionManager> manager = solver->getManager().getSharedPointer();
solver->add(countConstr->toExpression(varNames, manager));
storm::solver::SmtSolver::CheckResult res = solver->check();
solver->pop();
return res;
}
uint64_t DFTASFChecker::correctLowerBound(uint64_t bound, uint_fast64_t timeout) {
STORM_LOG_ASSERT(solver, "SMT Solver was not initialized, call toSolver() before checking queries");
STORM_LOG_DEBUG("Lower bound correction - try to correct bound " << std::to_string(bound));
// placeholder, set lower bound to 1 to prevent loss of precision
return 1;
// TODO correction mechanism
// easy method ("climb down" all direct predecessor states of bound) does not work
while (bound >= 0) {
setSolverTimeout(timeout * 1000);
storm::solver::SmtSolver::CheckResult tmp_res = checkFailsWithLessThanMarkovianState(bound);
unsetSolverTimeout();
switch (tmp_res) {
case storm::solver::SmtSolver::CheckResult::Unsat:
STORM_LOG_DEBUG("Lower bound correction - corrected bound to " << std::to_string(bound));
return bound;
case storm::solver::SmtSolver::CheckResult::Unknown:
STORM_LOG_DEBUG("Lower bound correction - Solver returned 'Unknown', corrected to ");
return bound;
default:
--bound;
break;
}
}
return bound;
}
uint64_t DFTASFChecker::getLeastFailureBound(uint_fast64_t timeout) {
@ -524,7 +568,7 @@ namespace storm {
switch (tmp_res) {
case storm::solver::SmtSolver::CheckResult::Sat:
if (dft.getDependencies().size() > 0) {
return correctLowerBound(bound);
return correctLowerBound(bound, timeout);
} else {
return bound;
}

13
src/storm-dft/modelchecker/dft/DFTASFChecker.h

@ -95,14 +95,23 @@ namespace storm {
void unsetSolverTimeout();
private:
/**
* Helper function that checks if the DFT can fail while visiting less than a given number of Markovian states
*
* @param checkNumber the number to check against
* @return "Sat" if a sequence of BE failures exists such that less than checkNumber Markovian states are visited,
* "Unsat" if it does not, otherwise "Unknown"
*/
storm::solver::SmtSolver::CheckResult checkFailsWithLessThanMarkovianState(uint64_t checkNumber);
/**
* Helper function for correction of least failure bound when dependencies are present
*
* @param state number of the state in the sequence to check
* @param bound known lower bound to be corrected
* @param timeout timeout timeout for each query in seconds
* @return the corrected bound, 1 if correction cannot be completed
*/
uint64_t correctLowerBound(uint64_t bound);
uint64_t correctLowerBound(uint64_t bound, uint_fast64_t timeout);
uint64_t getClaimVariableIndex(uint64_t spareIndex, uint64_t childIndex) const;

33
src/storm-dft/modelchecker/dft/SmtConstraint.cpp

@ -597,6 +597,39 @@ namespace storm {
std::shared_ptr<SmtConstraint> thenConstraint;
std::shared_ptr<SmtConstraint> elseConstraint;
};
class BoolCountIsLessConstant : public SmtConstraint {
public:
BoolCountIsLessConstant(std::vector<uint64_t> varIndices, uint64_t val) : varIndices(varIndices),
value(val) {
}
std::string toSmtlib2(std::vector<std::string> const &varNames) const override {
std::stringstream sstr;
sstr << "(< (+ ";
for (uint64_t i = 0; i < varIndices.size(); ++i) {
sstr << "(ite " << varNames.at(varIndices.at(i)) << " 1 0 )";
}
sstr << ") " << value << " )";
return sstr.str();
}
storm::expressions::Expression toExpression(std::vector<std::string> const &varNames,
std::shared_ptr<storm::expressions::ExpressionManager> manager) const override {
std::vector<storm::expressions::Expression> boolToInt;
for (uint64_t i = 0; i < varIndices.size(); ++i) {
boolToInt.push_back(
ite(manager->getVariableExpression(varNames.at(varIndices.at(i))), // If variable is true
manager->integer(1), // set 1
manager->integer(0))); // else 0
}
return sum(boolToInt) < manager->integer(value);
}
private:
std::vector<uint64_t> varIndices;
uint64_t value;
};
}
}
Loading…
Cancel
Save