Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SmtMinimalLabelSetGeneratorTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
4#include <optional>
5
6#ifdef STORM_HAVE_Z3
7
11#include "storm/api/builder.h"
16
17namespace {
18
22std::optional<storm::jani::Model> computeJaniCounterexample(std::string const& janiFile, std::string const& formulaString) {
24 auto properties = storm::api::parsePropertiesForSymbolicModelDescription(formulaString, modelDescription);
25 auto formula = storm::api::extractFormulasFromProperties(properties).front();
26
27 storm::builder::BuilderOptions options(*formula);
28 options.setBuildChoiceOrigins(true);
29 auto model = storm::api::buildSparseModel<double>(modelDescription, options);
30
31 auto counterexample = storm::api::computeHighLevelCounterexampleMaxSmt(storm::Environment(), modelDescription, model, formula);
32 auto highLevelCounterexample = std::dynamic_pointer_cast<storm::counterexamples::HighLevelCounterexample>(counterexample);
33 if (highLevelCounterexample != nullptr && highLevelCounterexample->isJaniHighLevelCounterexample()) {
34 return highLevelCounterexample->getModelDescription().asJaniModel();
35 }
36 ADD_FAILURE() << "Failed to compute a high-level counterexample for jani file " << janiFile << " and " << formulaString << ".";
37 return std::nullopt;
38}
39
40uint64_t getNumberOfEdges(storm::jani::Model const& model) {
41 uint64_t result = 0;
42 for (auto const& automaton : model.getAutomata()) {
43 result += automaton.getNumberOfEdges();
44 }
45 return result;
46}
47
48// The generator reasons symbolically about which edges can enable each other. Since the location of an automaton is
49// not part of the variable valuation, that reasoning has to take the source and target locations of the edges into
50// account. Models that keep their control flow in locations rather than in variables (as, e.g., models exported by
51// Modest do) used to make the generator fail with a 'map::at: key not found' error.
52TEST(SmtMinimalLabelSetGeneratorTest, DtmcWithMultipleLocations) {
53 // The automaton moves from l0 either to l1 (probability 0.9) or to l2 (probability 0.1) and only reaches the
54 // target state s=3 via l2. All guards are trivially true, so the location is the only thing distinguishing the
55 // edges. The minimal counterexample consists of the initial edge and the edge in l2, but not the one in l1.
56 auto result = computeJaniCounterexample(STORM_TEST_RESOURCES_DIR "/dtmc/locations_counterexample.jani", "P<0.05 [ F s=3 ]");
57 ASSERT_TRUE(result.has_value());
58 ASSERT_EQ(1ull, result->getNumberOfAutomata());
59 ASSERT_EQ(2ull, getNumberOfEdges(result.value()));
60
61 storm::jani::Automaton const& automaton = result->getAutomaton(0);
62 EXPECT_EQ(automaton.getLocationIndex("l0"), automaton.getEdge(0).getSourceLocationIndex());
63 EXPECT_EQ(automaton.getLocationIndex("l2"), automaton.getEdge(1).getSourceLocationIndex());
64}
65
66TEST(SmtMinimalLabelSetGeneratorTest, MdpWithMultipleLocationsAndInitialLocations) {
67 // Automaton A is as in the DTMC above, but its first edge synchronizes with automaton B, which has two initial
68 // locations. As the property value is the maximum over the initial states, it suffices to keep the edge of B that
69 // is enabled in one of the two initial locations. The edge of A in l1 is not needed.
70 auto result = computeJaniCounterexample(STORM_TEST_RESOURCES_DIR "/mdp/locations_counterexample.jani", "P<0.5 [ F s=3 ]");
71 ASSERT_TRUE(result.has_value());
72
73 ASSERT_EQ(2ull, result->getNumberOfAutomata());
74 EXPECT_EQ(2ull, result->getAutomaton("A").getNumberOfEdges());
75 // Either edge of B yields a counterexample, so we only check how many of them are kept.
76 EXPECT_EQ(1ull, result->getAutomaton("B").getNumberOfEdges());
77}
78
79} // namespace
80
81#endif
TEST(RegionConstraintCheckerTest, AffineConstraintHoldsThroughout)
Edge const & getEdge(uint64_t index) const
Retrieves the edge with the given index in this automaton.
uint64_t getLocationIndex(std::string const &name) const
uint64_t getSourceLocationIndex() const
Retrieves the index of the source location.
Definition Edge.cpp:41
std::vector< Automaton > & getAutomata()
Retrieves the automata of the model.
Definition Model.cpp:868
std::shared_ptr< storm::counterexamples::Counterexample > computeHighLevelCounterexampleMaxSmt(storm::Environment const &env, storm::storage::SymbolicModelDescription const &symbolicModel, std::shared_ptr< storm::models::sparse::Model< double > > model, std::shared_ptr< storm::logic::Formula const > const &formula, storm::counterexamples::SMTMinimalLabelSetGenerator< double >::Options const &options)
std::shared_ptr< storm::models::sparse::Model< ValueType > > buildSparseModel(storm::storage::SymbolicModelDescription const &model, storm::builder::BuilderOptions const &options, typename storm::builder::ExplicitModelBuilder< ValueType >::Options const &explorationOptions=typename storm::builder::ExplicitModelBuilder< ValueType >::Options())
Definition builder.h:117
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
std::vector< storm::jani::Property > parsePropertiesForSymbolicModelDescription(std::string const &inputString, storm::storage::SymbolicModelDescription const &modelDescription, boost::optional< std::set< std::string > > const &propertyFilter)
std::pair< storm::jani::Model, std::vector< storm::jani::Property > > parseJaniModel(std::string const &filename, boost::optional< std::vector< std::string > > const &propertyFilter)