Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
NonMarkovianChainTransformer.cpp
Go to the documentation of this file.
2
14#include "storm/utility/graph.h"
17
18namespace storm {
19namespace transformer {
20
21template<typename ValueType, typename RewardModelType>
22std::shared_ptr<models::sparse::Model<ValueType, RewardModelType>> NonMarkovianChainTransformer<ValueType, RewardModelType>::eliminateNonmarkovianStates(
24 STORM_LOG_THROW(ma->isClosed(), storm::exceptions::InvalidModelException, "MA should be closed first.");
25
26 if (ma->getMarkovianStates().full()) {
27 // Is already a CTMC
28 return ma->convertToCtmc();
29 }
30
32 "Labels are not preserved! Results may be incorrect. Continue at your own caution.");
33
34 // Initialize
35 storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(ma->getTransitionMatrix());
36 storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(ma->getTransitionMatrix().transpose(), true);
37 storm::models::sparse::StateLabeling stateLabeling = ma->getStateLabeling();
38 // TODO: update reward models and choice labels according to kept states
39 STORM_LOG_WARN_COND(ma->getRewardModels().empty(), "Reward models are not preserved in chain elimination.");
40 std::unordered_map<std::string, RewardModelType> rewardModels;
41 STORM_LOG_WARN_COND(!ma->hasChoiceLabeling(), "Choice labels are not preserved in chain elimination.");
42 STORM_LOG_WARN_COND(!ma->hasStateValuations(), "State valuations are not preserved in chain elimination.");
43 STORM_LOG_WARN_COND(!ma->hasChoiceOrigins(), "Choice origins are not preserved in chain elimination.");
44
45 // Eliminate all probabilistic states by state elimination
46 auto actionRewards = std::vector<ValueType>(ma->getTransitionMatrix().getRowCount(), storm::utility::zero<ValueType>());
47 storm::solver::stateelimination::NondeterministicModelStateEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions,
48 actionRewards);
49 storm::storage::BitVector keepStates(ma->getNumberOfStates(), true);
50
51 for (uint_fast64_t state = 0; state < ma->getNumberOfStates(); ++state) {
52 STORM_LOG_ASSERT(!ma->isHybridState(state), "State is hybrid.");
53 if (ma->isProbabilisticState(state)) {
54 // Only eliminate immediate states (and no Markovian states)
55 if (ma->getNumberOfChoices(state) <= 1) {
56 // Eliminate only if no non-determinism occurs
57 STORM_LOG_ASSERT(ma->getNumberOfChoices(state) == 1, "State " << state << " has no choices.");
58 STORM_LOG_ASSERT(flexibleMatrix.getRowGroupSize(state) == 1, "State " << state << " has too many rows.");
59
60 bool eliminate = true;
61
62 // Handle labels according to given behavior
63 switch (labelBehavior) {
65 // Only eliminate if eliminated state and all its successors have the same labels
66 auto currLabels = stateLabeling.getLabelsOfState(state);
67 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
68 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
69 if (currLabels != stateLabeling.getLabelsOfState(entryIt->getColumn())) {
70 STORM_LOG_TRACE("Do not eliminate state " << state << " because labels of state " << entryIt->getColumn() << " are different.");
71 eliminate = false;
72 break;
73 }
74 }
75 break;
76 }
78 // Only eliminate if labels of eliminated state are contained in labels of each successor states
79 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
80 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
81 auto labelsState = stateLabeling.getLabelsOfState(state);
82 auto labelsSuccessor = stateLabeling.getLabelsOfState(entryIt->getColumn());
83 if (!std::includes(labelsSuccessor.begin(), labelsSuccessor.end(), labelsState.begin(), labelsState.end())) {
84 STORM_LOG_TRACE("Do not eliminate state " << state << " because labels of state " << entryIt->getColumn()
85 << " are not included.");
86 eliminate = false;
87 break;
88 }
89 }
90 break;
91 }
93 // Eliminate state and add its labels to the successor states
94 // As helper for the labeling we create a bitvector representing all successor states
95 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
96 storm::storage::BitVector successors(stateLabeling.getNumberOfItems());
97 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
98 successors.set(entryIt->getColumn());
99 }
100 // Add labels from eliminated state to successors
101 for (std::string const& label : stateLabeling.getLabelsOfState(state)) {
102 storm::storage::BitVector states = stateLabeling.getStates(label);
103 // Add successor states for this label as well
104 stateLabeling.setStates(label, states | successors);
105 }
106 break;
107 }
109 // Do not add labels from eliminated state, only exception is label for initial states
110 if (stateLabeling.getStateHasLabel("init", state)) {
111 storm::storage::BitVector initialStates = stateLabeling.getStates("init");
112 // As helper for the labeling we create a bitvector representing all successor states
113 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
114 storm::storage::BitVector successors(stateLabeling.getNumberOfItems());
115 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
116 successors.set(entryIt->getColumn());
117 }
118 // Add successor states to this label as well
119 stateLabeling.setStates("init", initialStates | successors);
120 }
121 break;
122 }
123 default:
124 STORM_LOG_ASSERT(false, "Unknown label behavior.");
125 break;
126 }
127
128 if (eliminate) {
129 stateEliminator.eliminateState(state, true);
130 keepStates.set(state, false);
131 }
132 }
133 }
134 }
135
136 // Create the new matrix
137 auto keptRows = ma->getTransitionMatrix().getRowFilter(keepStates);
138 storm::storage::SparseMatrix<ValueType> matrix = flexibleMatrix.createSparseMatrix(keptRows, keepStates);
139
140 // TODO: obtain the reward model for the resulting system
141
142 // Prepare model components
143 storm::storage::BitVector markovianStates = ma->getMarkovianStates() % keepStates;
144 storm::models::sparse::StateLabeling labeling = stateLabeling.getSubLabeling(keepStates);
145 storm::storage::sparse::ModelComponents<ValueType, RewardModelType> components(matrix, labeling, ma->getRewardModels(), false, markovianStates);
146 std::vector<ValueType> exitRates(markovianStates.size());
147 storm::utility::vector::selectVectorValues(exitRates, keepStates, ma->getExitRates());
148 components.exitRates = exitRates;
149
150 // Build transformed model
151 auto model = std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType, RewardModelType>>(std::move(components));
152 if (model->isConvertibleToCtmc()) {
153 return model->convertToCtmc();
154 } else {
155 return model;
156 }
157}
158
159template<typename ValueType, typename RewardModelType>
175
176template<typename ValueType, typename RewardModelType>
177std::vector<std::shared_ptr<storm::logic::Formula const>> NonMarkovianChainTransformer<ValueType, RewardModelType>::checkAndTransformFormulas(
178 std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
179 std::vector<std::shared_ptr<storm::logic::Formula const>> result;
180
181 for (auto const& f : formulas) {
182 if (preservesFormula(*f)) {
183 result.push_back(f);
184 } else {
185 STORM_LOG_WARN("Non-Markovian chain elimination does not preserve formula " << *f);
186 }
187 }
188 return result;
189}
190
193
196
197} // namespace transformer
198} // namespace storm
bool isInFragment(FragmentSpecification const &fragment) const
Definition Formula.cpp:204
FragmentSpecification & setNextFormulasAllowed(bool newValue)
FragmentSpecification & setStepBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setGloballyFormulasAllowed(bool newValue)
FragmentSpecification & setTimeBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setReachabilityProbabilityFormulasAllowed(bool newValue)
FragmentSpecification & setBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setUntilFormulasAllowed(bool newValue)
FragmentSpecification & setProbabilityOperatorsAllowed(bool newValue)
std::size_t getNumberOfItems() const
Returns the number of items managed by this object.
This class represents a Markov automaton.
This class manages the labeling of the state space with a number of (atomic) labels.
bool getStateHasLabel(std::string const &label, storm::storage::sparse::state_type state) const
Checks whether a given state is labeled with the given label.
storm::storage::BitVector const & getStates(std::string const &label) const
Returns the labeling of states associated with the given label.
void setStates(std::string const &label, storage::BitVector const &labeling)
Sets the labeling of states associated with the given label.
std::set< std::string > getLabelsOfState(storm::storage::sparse::state_type state) const
Retrieves the set of labels attached to the given state.
StateLabeling getSubLabeling(storm::storage::BitVector const &states) const
Retrieves the sub labeling that represents the same labeling as the current one for all selected stat...
void eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions)
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
The flexible sparse matrix is used during state elimination.
index_type getRowGroupSize(index_type group) const
Returns the size of the given row group.
storm::storage::SparseMatrix< ValueType > createSparseMatrix()
Creates a sparse matrix from the flexible sparse matrix.
row_type & getRow(index_type)
Returns an object representing the given row.
std::vector< storm::storage::MatrixEntry< index_type, value_type > > row_type
A class that holds a possibly non-square matrix in the compressed row storage format.
Transformer for eliminating chains of non-Markovian states (instantaneous path fragment leading to th...
static std::shared_ptr< models::sparse::Model< ValueType, RewardModelType > > eliminateNonmarkovianStates(std::shared_ptr< models::sparse::MarkovAutomaton< ValueType, RewardModelType > > ma, EliminationLabelBehavior labelBehavior=EliminationLabelBehavior::KeepLabels)
Generates a model with the same basic behavior as the input, but eliminates non-Markovian chains.
static std::vector< std::shared_ptr< storm::logic::Formula const > > checkAndTransformFormulas(std::vector< std::shared_ptr< storm::logic::Formula const > > const &formulas)
Checks for the given formulae if the specified properties are preserved and removes formulae of prope...
static bool preservesFormula(storm::logic::Formula const &formula)
Check if the property specified by the given formula is preserved by the transformation.
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
FragmentSpecification propositional()
EliminationLabelBehavior
Specify criteria whether a state can be eliminated and how its labels should be treated.
void selectVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Selects the elements from a vector at the specified positions and writes them consecutively into anot...
Definition vector.h:184
boost::optional< std::vector< ValueType > > exitRates