Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
BinaryDtmcTransformer.cpp
Go to the documentation of this file.
2#include <carl/formula/Constraint.h>
3#include <cstdint>
4#include <queue>
5
10
15
16namespace storm {
17namespace transformer {
18std::shared_ptr<storm::models::sparse::Dtmc<RationalFunction>> BinaryDtmcTransformer::transform(storm::models::sparse::Dtmc<RationalFunction> const& dtmc,
19 bool keepStateValuations) const {
20 auto data = transformTransitions(dtmc);
22 components.stateLabeling = transformStateLabeling(dtmc, data);
23 for (auto const& rewModel : dtmc.getRewardModels()) {
24 components.rewardModels.emplace(rewModel.first, transformRewardModel(dtmc, rewModel.second, data));
25 }
26 components.transitionMatrix = std::move(data.simpleMatrix);
27 if (keepStateValuations && dtmc.hasStateValuations()) {
28 components.stateValuations = dtmc.getStateValuations().blowup(data.simpleStateToOriginalState);
29 }
30
31 return std::make_shared<storm::models::sparse::Dtmc<RationalFunction>>(std::move(components.transitionMatrix), std::move(components.stateLabeling),
32 std::move(components.rewardModels));
33}
34
36 uint64_t state;
37 std::vector<storage::MatrixEntry<uint64_t, RationalFunction>> row;
38};
39
40typename BinaryDtmcTransformer::TransformationData BinaryDtmcTransformer::transformTransitions(
42 auto const& matrix = dtmc.getTransitionMatrix();
43
44 // Initialize a FIFO Queue that stores the start and the end of each row
45 std::queue<StateWithRow> queue;
46 for (uint64_t state = 0; state < matrix.getRowCount(); ++state) {
47 std::vector<storage::MatrixEntry<uint64_t, RationalFunction>> diyRow;
48 for (auto const& entry : matrix.getRow(state)) {
49 diyRow.push_back(entry);
50 }
51 queue.emplace(StateWithRow{state, diyRow});
52 }
53
55 uint64_t currRow = 0;
56 uint64_t currAuxState = queue.size();
57 std::vector<uint64_t> origStates;
58
59 while (!queue.empty()) {
60 auto stateWithRow = std::move(queue.front());
61 queue.pop();
62
63 std::set<RationalFunctionVariable> variablesInRow;
64
65 for (auto const& entry : stateWithRow.row) {
66 for (auto const& variable : entry.getValue().gatherVariables()) {
67 variablesInRow.emplace(variable);
68 }
69 }
70
71 if (variablesInRow.size() == 0) {
72 // Insert the row directly
73 for (auto const& entry : stateWithRow.row) {
74 builder.addNextValue(currRow, entry.getColumn(), entry.getValue());
75 }
76 ++currRow;
77 } else if (variablesInRow.size() == 1) {
78 auto parameter = *variablesInRow.begin();
79 auto parameterPol = RawPolynomial(parameter);
80 auto oneMinusParameter = RawPolynomial(1) - parameterPol;
81
82 std::vector<storage::MatrixEntry<uint64_t, RationalFunction>> outgoing;
83 // p * .. state
84 std::vector<storage::MatrixEntry<uint64_t, RationalFunction>> newStateLeft;
85 // (1-p) * .. state
86 std::vector<storage::MatrixEntry<uint64_t, RationalFunction>> newStateRight;
87
88 RationalFunction sumOfLeftBranch;
89 RationalFunction sumOfRightBranch;
90
91 for (auto const& entry : stateWithRow.row) {
92 if (entry.getValue().isConstant()) {
93 outgoing.push_back(entry);
94 }
95 auto nominator = entry.getValue().nominator();
96 auto denominator = entry.getValue().denominator();
97 auto byP = RawPolynomial(nominator).divideBy(parameterPol);
98 if (byP.remainder.isZero()) {
99 auto probability = RationalFunction(carl::makePolynomial<Polynomial>(byP.quotient), denominator);
100 newStateLeft.push_back(storage::MatrixEntry<uint64_t, RationalFunction>(entry.getColumn(), probability));
101 sumOfLeftBranch += probability;
102 continue;
103 }
104 auto byOneMinusP = RawPolynomial(nominator).divideBy(oneMinusParameter);
105 if (byOneMinusP.remainder.isZero()) {
106 auto probability = RationalFunction(carl::makePolynomial<Polynomial>(byOneMinusP.quotient), denominator);
107 newStateRight.push_back(storage::MatrixEntry<uint64_t, RationalFunction>(entry.getColumn(), probability));
108 sumOfRightBranch += probability;
109 continue;
110 }
111 STORM_LOG_ERROR("Invalid transition!");
112 }
113 sumOfLeftBranch.simplify();
114 sumOfRightBranch.simplify();
115 for (auto& entry : newStateLeft) {
116 entry.setValue(entry.getValue() / sumOfLeftBranch);
117 }
118 for (auto& entry : newStateRight) {
119 entry.setValue(entry.getValue() / sumOfRightBranch);
120 }
121
122 queue.push(StateWithRow{currAuxState, newStateLeft});
123 outgoing.push_back(storage::MatrixEntry<uint64_t, RationalFunction>(
124 currAuxState, (sumOfLeftBranch)*RationalFunction(carl::makePolynomial<Polynomial>(parameter))));
125 ++currAuxState;
126 queue.push(StateWithRow{currAuxState, newStateRight});
127 outgoing.push_back(storage::MatrixEntry<uint64_t, RationalFunction>(
128 currAuxState, (sumOfRightBranch) * (utility::one<RationalFunction>() - RationalFunction(carl::makePolynomial<Polynomial>(parameter)))));
129 ++currAuxState;
130
131 for (auto const& entry : outgoing) {
132 builder.addNextValue(currRow, entry.getColumn(), entry.getValue());
133 }
134 ++currRow;
135 } else {
136 STORM_LOG_ERROR("More than one variable in row " << currRow << "!");
137 }
138 origStates.push_back(stateWithRow.state);
139 }
140 TransformationData result;
141 result.simpleMatrix = builder.build(currRow, currAuxState, currAuxState);
142 result.simpleStateToOriginalState = std::move(origStates);
143 return result;
144}
145
146storm::models::sparse::StateLabeling BinaryDtmcTransformer::transformStateLabeling(storm::models::sparse::Dtmc<RationalFunction> const& dtmc,
147 TransformationData const& data) const {
148 storm::models::sparse::StateLabeling labeling(data.simpleMatrix.getRowCount());
149 for (auto const& labelName : dtmc.getStateLabeling().getLabels()) {
150 storm::storage::BitVector newStates = dtmc.getStateLabeling().getStates(labelName);
151 newStates.resize(data.simpleMatrix.getRowCount(), false);
152 if (labelName != "init") {
153 for (uint64_t newState = dtmc.getNumberOfStates(); newState < data.simpleMatrix.getRowCount(); ++newState) {
154 newStates.set(newState, newStates[data.simpleStateToOriginalState[newState]]);
155 }
156 }
157 labeling.addLabel(labelName, std::move(newStates));
158 }
159 return labeling;
160}
161
162storm::models::sparse::StandardRewardModel<RationalFunction> BinaryDtmcTransformer::transformRewardModel(
164 TransformationData const& data) const {
165 std::optional<std::vector<RationalFunction>> stateRewards, actionRewards;
166 STORM_LOG_THROW(rewardModel.hasStateActionRewards(), storm::exceptions::NotSupportedException, "Only state rewards supported.");
167 if (rewardModel.hasStateRewards()) {
168 stateRewards = rewardModel.getStateRewardVector();
169 stateRewards->resize(data.simpleMatrix.getRowCount(), storm::utility::zero<RationalFunction>());
170 }
171 return storm::models::sparse::StandardRewardModel<RationalFunction>(std::move(stateRewards), std::move(actionRewards));
172}
173} // namespace transformer
174} // namespace storm
This class represents a discrete-time Markov chain.
Definition Dtmc.h:14
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:197
std::unordered_map< std::string, RewardModelType > const & getRewardModels() const
Retrieves the reward models.
Definition Model.cpp:699
bool hasStateValuations() const
Retrieves whether this model was build with state valuations.
Definition Model.cpp:349
storm::storage::sparse::StateValuations const & getStateValuations() const
Retrieves the valuations of the states of the model.
Definition Model.cpp:354
storm::models::sparse::StateLabeling const & getStateLabeling() const
Returns the state labeling associated with this model.
Definition Model.cpp:319
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:162
std::vector< ValueType > const & getStateRewardVector() const
Retrieves the state rewards of the reward model.
bool hasStateRewards() const
Retrieves whether the reward model has state rewards.
bool hasStateActionRewards() const
Retrieves whether the reward model has state-action rewards.
This class manages the labeling of the state space with a number of (atomic) labels.
storm::storage::BitVector const & getStates(std::string const &label) const
Returns the labeling of states associated with the given label.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
void resize(uint_fast64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
StateValuations blowup(std::vector< uint64_t > const &mapNewToOld) const
std::shared_ptr< storm::models::sparse::Dtmc< RationalFunction > > transform(storm::models::sparse::Dtmc< RationalFunction > const &dtmc, bool keepStateValuations=false) const
Transforms a pDTMC that has linear transitions (e.g.
#define STORM_LOG_ERROR(message)
Definition logging.h:31
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
NumberTraits< RationalType >::IntegerType denominator(RationalType const &number)
LabParser.cpp.
Definition cli.cpp:18
carl::RationalFunction< Polynomial, true > RationalFunction
carl::MultivariatePolynomial< RationalFunctionCoefficient > RawPolynomial
std::optional< storm::storage::sparse::StateValuations > stateValuations
std::unordered_map< std::string, RewardModelType > rewardModels
storm::storage::SparseMatrix< ValueType > transitionMatrix
storm::models::sparse::StateLabeling stateLabeling
std::vector< storage::MatrixEntry< uint64_t, RationalFunction > > row