45 std::set<std::string> labelsInFormula;
46 for (
auto const& atomicLabelFormula : checkTask.
getFormula().getAtomicLabelFormulas()) {
47 labelsInFormula.emplace(atomicLabelFormula->getLabel());
53 boost::optional<std::vector<RationalFunction>> stateRewardVector;
54 boost::optional<std::string> stateRewardName;
55 if (checkTask.
getFormula().isRewardOperatorFormula()) {
62 stateRewardVector = dtmc.
getRewardModel(
"").getStateRewardVector();
67 auto const constantVariable = carl::VariablePool::getInstance().getFreshPersistentVariable();
68 auto topologicalOrdering = utility::graph::getTopologicalSort<RationalFunction>(transitionMatrix, {initialState});
71 std::stack<uint64_t> topologicalOrderingStack;
72 for (
auto rit = topologicalOrdering.begin(); rit != topologicalOrdering.end(); ++rit) {
73 topologicalOrderingStack.push(*rit);
77 std::map<RationalFunctionVariable, std::map<uint64_t, std::set<uint64_t>>> treeStates;
78 std::map<RationalFunctionVariable, std::set<uint64_t>> workingSets;
80 auto backwardsTransitions = flexibleMatrix.createSparseMatrix().transpose(
true);
82 for (uint64_t row = 0; row < flexibleMatrix.getRowCount(); row++) {
83 for (
auto const& entry : flexibleMatrix.getRow(row)) {
84 if (entry.getValue().isConstant()) {
87 STORM_LOG_ERROR_COND(entry.getValue().gatherVariables().size() == 1,
"Flip minimization only supports transitions with a single parameter.");
88 auto parameter = *entry.getValue().gatherVariables().begin();
89 auto cache = entry.getValue().nominatorAsPolynomial().pCache();
90 STORM_LOG_ERROR_COND(entry.getValue().denominator().isOne() && entry.getValue().nominator().isUnivariate() &&
91 entry.getValue().nominator().getSingleVariable() == parameter && entry.getValue().nominator().factorization().size() == 1,
92 "Flip minimization only supports simple pMCs.");
93 STORM_LOG_ERROR_COND(flexibleMatrix.getRow(row).size() == 2,
"Flip minimization only supports transitions with a single parameter.");
94 workingSets[parameter].emplace(row);
95 treeStates[parameter][row].emplace(row);
96 if (
utility::isOne(entry.getValue().derivative(entry.getValue().nominator().getSingleVariable()))) {
97 }
else if (
utility::isOne(-entry.getValue().derivative(entry.getValue().nominator().getSingleVariable()))) {
99 STORM_LOG_ERROR_COND(
false,
"Flip minimization only supports transitions with a single parameter.");
106 std::set<std::pair<RationalFunctionVariable, std::set<uint64_t>>> alreadyReorderedWrt;
108 updateTreeStates(treeStates, workingSets, flexibleMatrix, allParameters, stateRewardVector, runningLabeling, labelsInFormula);
109 while (!topologicalOrderingStack.empty()) {
110 auto state = topologicalOrderingStack.top();
111 topologicalOrderingStack.pop();
113 bool performJipConvert =
false;
114 bool reorderingPossible =
false;
116 bool alreadyReorderedWrtThis =
true;
117 for (
auto const& parameter : allParameters) {
118 if (!treeStates[parameter].count(state)) {
122 auto const entry = treeStates.at(parameter).at(state);
123 if (entry.size() >= 2) {
124 performJipConvert =
true;
125 reorderingPossible =
true;
129 std::set<uint64_t> entriesInOldDtmc;
131 std::copy_if(entry.begin(), entry.end(), std::inserter(entriesInOldDtmc, entriesInOldDtmc.end()),
132 [statesOfDtmc](uint64_t value) { return value < statesOfDtmc; });
135 if (alreadyReorderedWrt.count(std::make_pair(parameter, entriesInOldDtmc)) == 0) {
136 alreadyReorderedWrtThis =
false;
138 alreadyReorderedWrt.emplace(std::make_pair(parameter, entry));
141 if (!performJipConvert || alreadyReorderedWrtThis) {
144 std::map<uint64_t, bool> alreadyVisited;
145 collapseConstantTransitions(state, flexibleMatrix, alreadyVisited, treeStates, allParameters, stateRewardVector, runningLabeling, labelsInFormula);
149 if (stateRewardVector) {
154 storm::io::openFile(
"dots/jipconvert_" + std::to_string(flexibleMatrix.getRowCount()) +
".dot", file);
162 if (reorderingPossible) {
163 std::map<storm::RationalFunctionVariable, std::set<uint64_t>> parameterBuckets;
164 std::map<storm::RationalFunctionVariable, RationalFunction> cumulativeProbabilities;
166 std::map<uint64_t, uint64_t> pTransitions;
167 std::map<uint64_t, uint64_t> oneMinusPTransitions;
169 std::map<uint64_t, RationalFunction> directProbs;
171 std::map<storm::RationalFunctionVariable, RationalFunction> pRationalFunctions;
172 std::map<storm::RationalFunctionVariable, RationalFunction> oneMinusPRationalFunctions;
174 for (
auto const& entry : flexibleMatrix.getRow(state)) {
176 if (stateRewardVector && !stateRewardVector->at(entry.getColumn()).isZero()) {
177 parameterBuckets[constantVariable].emplace(entry.getColumn());
178 cumulativeProbabilities[constantVariable] += entry.getValue();
179 directProbs[entry.getColumn()] = entry.getValue();
183 for (
auto const& entry2 : flexibleMatrix.getRow(entry.getColumn())) {
184 if (entry2.getValue().isZero()) {
187 if (entry2.getValue().isConstant()) {
188 parameterOfSuccessor = constantVariable;
193 "Flip minimization only supports transitions with a single parameter.");
194 parameterOfSuccessor = *entry2.getValue().gatherVariables().begin();
195 auto cache = entry2.getValue().nominatorAsPolynomial().pCache();
196 STORM_LOG_ERROR_COND(entry2.getValue().denominator().isOne() && entry2.getValue().nominator().isUnivariate() &&
197 entry2.getValue().nominator().getSingleVariable() == parameterOfSuccessor &&
198 entry2.getValue().nominator().factorization().size() == 1,
199 "Flip minimization only supports simple pMCs.");
201 "Flip minimization only supports transitions with a single parameter.");
202 if (
utility::isOne(entry2.getValue().derivative(entry2.getValue().nominator().getSingleVariable()))) {
203 pRationalFunctions[parameterOfSuccessor] = entry2.getValue();
204 pTransitions[entry.getColumn()] = entry2.getColumn();
205 }
else if (
utility::isOne(-entry2.getValue().derivative(entry2.getValue().nominator().getSingleVariable()))) {
206 oneMinusPRationalFunctions[parameterOfSuccessor] = entry2.getValue();
207 oneMinusPTransitions[entry.getColumn()] = entry2.getColumn();
209 STORM_LOG_ERROR_COND(
false,
"Flip minimization only supports transitions with a single parameter.");
212 parameterBuckets[parameterOfSuccessor].emplace(entry.getColumn());
213 cumulativeProbabilities[parameterOfSuccessor] += entry.getValue();
214 directProbs[entry.getColumn()] = entry.getValue();
218 uint64_t newMatrixSize = flexibleMatrix.getRowCount() + 3 * parameterBuckets.size();
219 if (parameterBuckets.count(constantVariable)) {
224 for (uint64_t row = 0; row < flexibleMatrix.getRowCount(); row++) {
225 matrixWithAdditionalStates.
getRow(row) = flexibleMatrix.getRow(row);
230 uint64_t newStateIndex = flexibleMatrix.getRowCount();
231 matrixWithAdditionalStates.
getRow(state).clear();
232 for (
auto const& entry : parameterBuckets) {
233 matrixWithAdditionalStates.
getRow(state).push_back(
237 if (entry.first == constantVariable) {
238 for (
auto const& successor : entry.second) {
239 matrixWithAdditionalStates.
getRow(newStateIndex)
241 directProbs.at(successor) / cumulativeProbabilities.at(entry.first)));
245 matrixWithAdditionalStates.
getRow(newStateIndex) = joinDuplicateTransitions(matrixWithAdditionalStates.
getRow(newStateIndex));
247 workingSets[entry.first].emplace(newStateIndex);
248 for (
auto const& entry : matrixWithAdditionalStates.
getRow(newStateIndex)) {
249 for (
auto const& parameter : allParameters) {
250 workingSets[parameter].emplace(entry.getColumn());
256 matrixWithAdditionalStates.
getRow(newStateIndex)
258 matrixWithAdditionalStates.
getRow(newStateIndex)
261 for (
auto const& successor : entry.second) {
263 for (
auto& state : treeStates.at(entry.first)) {
264 if (state.first != successor) {
265 state.second.erase(successor);
269 workingSets[entry.first].emplace(successor);
271 matrixWithAdditionalStates.
getRow(newStateIndex + 1)
273 directProbs.at(successor) / cumulativeProbabilities.at(entry.first)));
274 matrixWithAdditionalStates.
getRow(newStateIndex + 2)
276 directProbs.at(successor) / cumulativeProbabilities.at(entry.first)));
280 matrixWithAdditionalStates.
getRow(newStateIndex + 1) = joinDuplicateTransitions(matrixWithAdditionalStates.
getRow(newStateIndex + 1));
281 matrixWithAdditionalStates.
getRow(newStateIndex + 2) = joinDuplicateTransitions(matrixWithAdditionalStates.
getRow(newStateIndex + 2));
283 treeStates[entry.first][newStateIndex].emplace(newStateIndex);
284 workingSets[entry.first].emplace(newStateIndex);
285 workingSets[entry.first].emplace(newStateIndex + 1);
286 workingSets[entry.first].emplace(newStateIndex + 2);
288 for (
auto const& entry : matrixWithAdditionalStates.
getRow(newStateIndex + 1)) {
289 for (
auto const& parameter : allParameters) {
290 workingSets[parameter].emplace(entry.getColumn());
293 for (
auto const& entry : matrixWithAdditionalStates.
getRow(newStateIndex + 2)) {
294 for (
auto const& parameter : allParameters) {
295 workingSets[parameter].emplace(entry.getColumn());
305 extendStateLabeling(runningLabeling, flexibleMatrix.getRowCount(), newMatrixSize, state, labelsInFormula);
307 for (uint64_t i = flexibleMatrix.getRowCount(); i < newMatrixSize; i++) {
309 topologicalOrderingStack.push(i);
311 if (stateRewardVector) {
312 stateRewardVector->push_back(storm::utility::zero<RationalFunction>());
315 runningLabeling = nextNewLabels;
317 updateTreeStates(treeStates, workingSets, matrixWithAdditionalStates, allParameters, stateRewardVector, runningLabeling, labelsInFormula);
319 flexibleMatrix = matrixWithAdditionalStates;
326 if (stateRewardVector) {
331 storm::io::openFile(
"dots/travel_" + std::to_string(flexibleMatrix.getRowCount()) +
".dot", file2);
337 transitionMatrix = flexibleMatrix.createSparseMatrix();
344 initialStates.
set(initialState,
true);
346 transitionMatrix = transitionMatrix.
getSubmatrix(
false, reachableStates, reachableStates);
347 runningLabeling = runningLabeling.
getSubLabeling(reachableStates);
348 uint64_t newInitialState = 0;
349 for (uint64_t i = 0; i < initialState; i++) {
350 if (reachableStates.
get(i)) {
354 initialState = newInitialState;
355 if (stateRewardVector) {
356 std::vector<RationalFunction> newStateRewardVector;
357 for (uint64_t i = 0; i < stateRewardVector->size(); i++) {
358 if (reachableStates.
get(i)) {
359 newStateRewardVector.push_back(stateRewardVector->at(i));
364 stateRewardVector = newStateRewardVector;
371 newInitialStates.
set(initialState,
true);
374 if (stateRewardVector) {