Matthias Volk
5 years ago
9 changed files with 170 additions and 15 deletions
-
1CHANGELOG.md
-
26src/storm-cli-utilities/model-handling.h
-
56src/storm-counterexamples/api/counterexamples.cpp
-
5src/storm-counterexamples/api/counterexamples.h
-
40src/storm-counterexamples/counterexamples/PathCounterexample.cpp
-
25src/storm-counterexamples/counterexamples/PathCounterexample.h
-
13src/storm-counterexamples/settings/modules/CounterexampleGeneratorSettings.cpp
-
17src/storm-counterexamples/settings/modules/CounterexampleGeneratorSettings.h
-
2src/storm/settings/modules/IOSettings.cpp
@ -1,19 +1,65 @@ |
|||
#include "storm-counterexamples/api/counterexamples.h"
|
|||
|
|||
#include "storm/environment/Environment.h"
|
|||
#include "storm/utility/shortestPaths.h"
|
|||
|
|||
namespace storm { |
|||
namespace api { |
|||
|
|||
std::shared_ptr<storm::counterexamples::Counterexample> computeHighLevelCounterexampleMilp(storm::storage::SymbolicModelDescription const& symbolicModel, std::shared_ptr<storm::models::sparse::Mdp<double>> mdp, std::shared_ptr<storm::logic::Formula const> const& formula) { |
|||
|
|||
std::shared_ptr<storm::counterexamples::Counterexample> |
|||
computeHighLevelCounterexampleMilp(storm::storage::SymbolicModelDescription const& symbolicModel, std::shared_ptr<storm::models::sparse::Mdp<double>> mdp, |
|||
std::shared_ptr<storm::logic::Formula const> const& formula) { |
|||
Environment env; |
|||
return storm::counterexamples::MILPMinimalLabelSetGenerator<double>::computeCounterexample(env, symbolicModel, *mdp, formula); |
|||
} |
|||
|
|||
std::shared_ptr<storm::counterexamples::Counterexample> computeHighLevelCounterexampleMaxSmt(storm::storage::SymbolicModelDescription const& symbolicModel, std::shared_ptr<storm::models::sparse::Model<double>> model, std::shared_ptr<storm::logic::Formula const> const& formula) { |
|||
|
|||
std::shared_ptr<storm::counterexamples::Counterexample> |
|||
computeHighLevelCounterexampleMaxSmt(storm::storage::SymbolicModelDescription const& symbolicModel, std::shared_ptr<storm::models::sparse::Model<double>> model, |
|||
std::shared_ptr<storm::logic::Formula const> const& formula) { |
|||
Environment env; |
|||
return storm::counterexamples::SMTMinimalLabelSetGenerator<double>::computeCounterexample(env, symbolicModel, *model, formula); |
|||
} |
|||
|
|||
|
|||
std::shared_ptr<storm::counterexamples::Counterexample> |
|||
computeKShortestPathCounterexample(std::shared_ptr<storm::models::sparse::Model<double>> model, std::shared_ptr<storm::logic::Formula const> const& formula, size_t maxK) { |
|||
// Only accept formulas of the form "P </<= x [F target]
|
|||
STORM_LOG_THROW(formula->isProbabilityOperatorFormula(), storm::exceptions::InvalidPropertyException, |
|||
"Counterexample generation does not support this kind of formula. Expecting a probability operator as the outermost formula element."); |
|||
storm::logic::ProbabilityOperatorFormula const& probabilityOperator = formula->asProbabilityOperatorFormula(); |
|||
STORM_LOG_THROW(probabilityOperator.hasBound(), storm::exceptions::InvalidPropertyException, "Counterexample generation only supports bounded formulas."); |
|||
STORM_LOG_THROW(!storm::logic::isLowerBound(probabilityOperator.getComparisonType()), storm::exceptions::InvalidPropertyException, |
|||
"Counterexample generation only supports upper bounds."); |
|||
double threshold = probabilityOperator.getThresholdAs<double>(); |
|||
storm::logic::Formula const& subformula = formula->asOperatorFormula().getSubformula(); |
|||
STORM_LOG_THROW(subformula.isEventuallyFormula(), storm::exceptions::InvalidPropertyException, |
|||
"Path formula is required to be of the form 'F psi' for counterexample generation."); |
|||
bool strictBound = (probabilityOperator.getComparisonType() == storm::logic::ComparisonType::Greater); |
|||
|
|||
// Perform model checking to get target states
|
|||
Environment env; |
|||
storm::modelchecker::SparsePropositionalModelChecker<storm::models::sparse::Model<double>> modelchecker(*model); |
|||
|
|||
storm::logic::EventuallyFormula const& eventuallyFormula = subformula.asEventuallyFormula(); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); |
|||
storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); |
|||
|
|||
auto generator = storm::utility::ksp::ShortestPathsGenerator<double>(*model, subQualitativeResult.getTruthValuesVector()); |
|||
storm::counterexamples::PathCounterexample<double> cex(model); |
|||
double probability = 0; |
|||
bool thresholdExceeded = false; |
|||
for (size_t k = 1; k <= maxK; ++k) { |
|||
cex.addPath(generator.getPathAsList(k), k); |
|||
probability += generator.getDistance(k); |
|||
// Check if accumulated probability mass is already enough
|
|||
if ((probability >= threshold && !strictBound) || (probability > threshold)) { |
|||
thresholdExceeded = true; |
|||
break; |
|||
} |
|||
} |
|||
STORM_LOG_WARN_COND(thresholdExceeded, "Aborted computation because maximal number of paths was reached. Probability threshold is not yet exceeded."); |
|||
|
|||
return std::make_shared<storm::counterexamples::PathCounterexample<double>>(cex); |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,40 @@ |
|||
#include "storm-counterexamples/counterexamples/PathCounterexample.h"
|
|||
|
|||
#include "storm/utility/export.h"
|
|||
|
|||
namespace storm { |
|||
namespace counterexamples { |
|||
|
|||
template<typename ValueType> |
|||
PathCounterexample<ValueType>::PathCounterexample(std::shared_ptr<storm::models::sparse::Model<ValueType>> model) : model(model) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void PathCounterexample<ValueType>::addPath(std::vector<storage::sparse::state_type> path, size_t k) { |
|||
if (k >= shortestPaths.size()) { |
|||
shortestPaths.resize(k); |
|||
} |
|||
shortestPaths[k-1] = path; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void PathCounterexample<ValueType>::writeToStream(std::ostream& out) const { |
|||
out << "Shortest path counterexample with k = " << shortestPaths.size() << " paths: " << std::endl; |
|||
for (size_t i = 0; i < shortestPaths.size(); ++i) { |
|||
out << i+1 << "-shortest path: " << std::endl; |
|||
for (auto it = shortestPaths[i].rbegin(); it != shortestPaths[i].rend(); ++it) { |
|||
out << "\tstate " << *it; |
|||
if (model->hasStateValuations()) { |
|||
out << ": "<< model->getStateValuations().getStateInfo(*it); |
|||
} |
|||
out << ": {"; |
|||
storm::utility::outputFixedWidth(out, model->getLabelsOfState(*it), 0); |
|||
out << "}" << std::endl; |
|||
} |
|||
} |
|||
} |
|||
|
|||
template class PathCounterexample<double>; |
|||
} |
|||
} |
@ -0,0 +1,25 @@ |
|||
#pragma once |
|||
|
|||
#include "storm-counterexamples/counterexamples/Counterexample.h" |
|||
|
|||
#include "storm/models/sparse/Model.h" |
|||
|
|||
namespace storm { |
|||
namespace counterexamples { |
|||
|
|||
template<typename ValueType> |
|||
class PathCounterexample : public Counterexample { |
|||
public: |
|||
PathCounterexample(std::shared_ptr<storm::models::sparse::Model<ValueType>> model); |
|||
|
|||
void addPath(std::vector<storage::sparse::state_type> path, size_t k); |
|||
|
|||
void writeToStream(std::ostream& out) const override; |
|||
|
|||
private: |
|||
std::shared_ptr<storm::models::sparse::Model<ValueType>> model; |
|||
std::vector<std::vector<storage::sparse::state_type>> shortestPaths; |
|||
}; |
|||
|
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue