Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
NonMarkovianChainTransformer.cpp
Go to the documentation of this file.
2
3#include <queue>
4
15#include "storm/utility/graph.h"
18
19namespace storm {
20namespace transformer {
21
22template<typename ValueType, typename RewardModelType>
23std::shared_ptr<models::sparse::Model<ValueType, RewardModelType>> NonMarkovianChainTransformer<ValueType, RewardModelType>::eliminateNonmarkovianStates(
25 STORM_LOG_THROW(ma->isClosed(), storm::exceptions::InvalidModelException, "MA should be closed first.");
26
27 if (ma->getMarkovianStates().full()) {
28 // Is already a CTMC
29 return ma->convertToCtmc();
30 }
31
33 "Labels are not preserved! Results may be incorrect. Continue at your own caution.");
34
35 // Initialize
36 storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(ma->getTransitionMatrix());
37 storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(ma->getTransitionMatrix().transpose(), true);
38 storm::models::sparse::StateLabeling stateLabeling = ma->getStateLabeling();
39 // TODO: update reward models and choice labels according to kept states
40 STORM_LOG_WARN_COND(ma->getRewardModels().empty(), "Reward models are not preserved in chain elimination.");
41 std::unordered_map<std::string, RewardModelType> rewardModels;
42 STORM_LOG_WARN_COND(!ma->hasChoiceLabeling(), "Choice labels are not preserved in chain elimination.");
43 STORM_LOG_WARN_COND(!ma->hasStateValuations(), "State valuations are not preserved in chain elimination.");
44 STORM_LOG_WARN_COND(!ma->hasChoiceOrigins(), "Choice origins are not preserved in chain elimination.");
45
46 // Eliminate all probabilistic states by state elimination
47 auto actionRewards = std::vector<ValueType>(ma->getTransitionMatrix().getRowCount(), storm::utility::zero<ValueType>());
48 storm::solver::stateelimination::NondeterministicModelStateEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions,
49 actionRewards);
50 storm::storage::BitVector keepStates(ma->getNumberOfStates(), true);
51
52 for (uint_fast64_t state = 0; state < ma->getNumberOfStates(); ++state) {
53 STORM_LOG_ASSERT(!ma->isHybridState(state), "State is hybrid.");
54 if (ma->isProbabilisticState(state)) {
55 // Only eliminate immediate states (and no Markovian states)
56 if (ma->getNumberOfChoices(state) <= 1) {
57 // Eliminate only if no non-determinism occurs
58 STORM_LOG_ASSERT(ma->getNumberOfChoices(state) == 1, "State " << state << " has no choices.");
59 STORM_LOG_ASSERT(flexibleMatrix.getRowGroupSize(state) == 1, "State " << state << " has too many rows.");
60
61 bool eliminate = true;
62
63 // Handle labels according to given behavior
64 switch (labelBehavior) {
66 // Only eliminate if eliminated state and all its successors have the same labels
67 auto currLabels = stateLabeling.getLabelsOfState(state);
68 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
69 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
70 if (currLabels != stateLabeling.getLabelsOfState(entryIt->getColumn())) {
71 STORM_LOG_TRACE("Do not eliminate state " << state << " because labels of state " << entryIt->getColumn() << " are different.");
72 eliminate = false;
73 break;
74 }
75 }
76 break;
77 }
79 // Only eliminate if labels of eliminated state are contained in labels of each successor states
80 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
81 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
82 auto labelsState = stateLabeling.getLabelsOfState(state);
83 auto labelsSuccessor = stateLabeling.getLabelsOfState(entryIt->getColumn());
84 if (!std::includes(labelsSuccessor.begin(), labelsSuccessor.end(), labelsState.begin(), labelsState.end())) {
85 STORM_LOG_TRACE("Do not eliminate state " << state << " because labels of state " << entryIt->getColumn()
86 << " are not included.");
87 eliminate = false;
88 break;
89 }
90 }
91 break;
92 }
94 // Eliminate state and add its labels to the successor states
95 // As helper for the labeling we create a bitvector representing all successor states
96 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
97 storm::storage::BitVector successors(stateLabeling.getNumberOfItems());
98 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
99 successors.set(entryIt->getColumn());
100 }
101 // Add labels from eliminated state to successors
102 for (std::string const& label : stateLabeling.getLabelsOfState(state)) {
103 storm::storage::BitVector states = stateLabeling.getStates(label);
104 // Add successor states for this label as well
105 stateLabeling.setStates(label, states | successors);
106 }
107 break;
108 }
110 // Do not add labels from eliminated state, only exception is label for initial states
111 if (stateLabeling.getStateHasLabel("init", state)) {
112 storm::storage::BitVector initialStates = stateLabeling.getStates("init");
113 // As helper for the labeling we create a bitvector representing all successor states
114 typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type entriesInRow = flexibleMatrix.getRow(state, 0); // Row group
115 storm::storage::BitVector successors(stateLabeling.getNumberOfItems());
116 for (auto entryIt = entriesInRow.begin(); entryIt != entriesInRow.end(); ++entryIt) {
117 successors.set(entryIt->getColumn());
118 }
119 // Add successor states to this label as well
120 stateLabeling.setStates("init", initialStates | successors);
121 }
122 break;
123 }
124 default:
125 STORM_LOG_ASSERT(false, "Unknown label behavior.");
126 break;
127 }
128
129 if (eliminate) {
130 stateEliminator.eliminateState(state, true);
131 keepStates.set(state, false);
132 }
133 }
134 }
135 }
136
137 // Create the new matrix
138 auto keptRows = ma->getTransitionMatrix().getRowFilter(keepStates);
139 storm::storage::SparseMatrix<ValueType> matrix = flexibleMatrix.createSparseMatrix(keptRows, keepStates);
140
141 // TODO: obtain the reward model for the resulting system
142
143 // Prepare model components
144 storm::storage::BitVector markovianStates = ma->getMarkovianStates() % keepStates;
145 storm::models::sparse::StateLabeling labeling = stateLabeling.getSubLabeling(keepStates);
146 storm::storage::sparse::ModelComponents<ValueType, RewardModelType> components(matrix, labeling, ma->getRewardModels(), false, markovianStates);
147 std::vector<ValueType> exitRates(markovianStates.size());
148 storm::utility::vector::selectVectorValues(exitRates, keepStates, ma->getExitRates());
149 components.exitRates = exitRates;
150
151 // Build transformed model
152 auto model = std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType, RewardModelType>>(std::move(components));
153 if (model->isConvertibleToCtmc()) {
154 return model->convertToCtmc();
155 } else {
156 return model;
157 }
158}
159
160template<typename ValueType, typename RewardModelType>
176
177template<typename ValueType, typename RewardModelType>
178std::vector<std::shared_ptr<storm::logic::Formula const>> NonMarkovianChainTransformer<ValueType, RewardModelType>::checkAndTransformFormulas(
179 std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
180 std::vector<std::shared_ptr<storm::logic::Formula const>> result;
181
182 for (auto const& f : formulas) {
183 if (preservesFormula(*f)) {
184 result.push_back(f);
185 } else {
186 STORM_LOG_WARN("Non-Markovian chain elimination does not preserve formula " << *f);
187 }
188 }
189 return result;
190}
191
194
197
198} // namespace transformer
199} // namespace storm
bool isInFragment(FragmentSpecification const &fragment) const
Definition Formula.cpp:196
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:18
void set(uint_fast64_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:30
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#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:189
LabParser.cpp.
Definition cli.cpp:18
boost::optional< std::vector< ValueType > > exitRates