From 6359119f489538fd227d2c8df9fe17d42d59e724 Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Fri, 24 May 2024 22:38:48 +0200 Subject: [PATCH 001/102] add assertions in a bug hunt --- src/storm/storage/SparseMatrix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/storm/storage/SparseMatrix.cpp b/src/storm/storage/SparseMatrix.cpp index 1dabffd458..962222783c 100644 --- a/src/storm/storage/SparseMatrix.cpp +++ b/src/storm/storage/SparseMatrix.cpp @@ -1336,6 +1336,7 @@ SparseMatrix SparseMatrix::selectRowsFromRowGroups(std::ve index_type subEntries = 0; for (index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) { // Determine which row we need to select from the current row group. + STORM_LOG_ASSERT(rowGroupToRowIndexMapping[rowGroupIndex] < this->getRowGroupSize(rowGroupIndex), "Cannot point to row offset " << rowGroupToRowIndexMapping[rowGroupIndex] << " for rowGroup " << rowGroupIndex << " which starts at " << this->getRowGroupIndices()[rowGroupIndex] << " and ends at " << this->getRowGroupIndices()[rowGroupIndex + 1] << "." ); index_type rowToCopy = this->getRowGroupIndices()[rowGroupIndex] + rowGroupToRowIndexMapping[rowGroupIndex]; // Iterate through that row and count the number of slots we have to reserve for copying. @@ -2353,6 +2354,7 @@ typename SparseMatrix::rows SparseMatrix::getRowGroup(inde template typename SparseMatrix::const_iterator SparseMatrix::begin(index_type row) const { + STORM_LOG_ASSERT(row < this->getRowCount(), "Row " << row << " exceeds row count " << this->getRowCount() << "."); return this->columnsAndValues.begin() + this->rowIndications[row]; } From da5e977e0215baa24d7310a09d5237a1960f4c13 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 24 Oct 2024 17:05:25 +0200 Subject: [PATCH 002/102] Verimon product in storm --- .../settings/PomdpSettings.cpp | 2 + .../GenerateMonitorVerifierSettings.cpp | 15 ++ .../modules/GenerateMonitorVerifierSettings.h | 21 ++ .../generator/GenerateMonitorVerifier.cpp | 196 ++++++++++++++++++ .../generator/GenerateMonitorVerifier.h | 25 +++ .../NondeterministicBeliefTracker.cpp | 1 + 6 files changed, 260 insertions(+) create mode 100644 src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp create mode 100644 src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.h create mode 100644 src/storm-pomdp/generator/GenerateMonitorVerifier.cpp create mode 100644 src/storm-pomdp/generator/GenerateMonitorVerifier.h diff --git a/src/storm-pomdp-cli/settings/PomdpSettings.cpp b/src/storm-pomdp-cli/settings/PomdpSettings.cpp index 7c7cdeb4fa..be6c2f48cd 100644 --- a/src/storm-pomdp-cli/settings/PomdpSettings.cpp +++ b/src/storm-pomdp-cli/settings/PomdpSettings.cpp @@ -30,6 +30,7 @@ #include "storm/settings/modules/TransformationSettings.h" #include "storm-pomdp-cli/settings/modules/BeliefExplorationSettings.h" +#include "storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.h" #include "storm-pomdp-cli/settings/modules/POMDPSettings.h" #include "storm-pomdp-cli/settings/modules/QualitativePOMDPAnalysisSettings.h" #include "storm-pomdp-cli/settings/modules/ToParametricSettings.h" @@ -68,6 +69,7 @@ void initializePomdpSettings(std::string const& name, std::string const& executa storm::settings::addModule(); storm::settings::addModule(); storm::settings::addModule(); + storm::settings::addModule(); } } // namespace settings } // namespace storm diff --git a/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp b/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp new file mode 100644 index 0000000000..37921d03a6 --- /dev/null +++ b/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp @@ -0,0 +1,15 @@ +#include "storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.h" + +namespace storm { +namespace settings { +namespace modules { + +const std::string GenerateMonitorVerifierSettings::moduleName = "generateMonitorVerifier"; + +GenerateMonitorVerifierSettings::GenerateMonitorVerifierSettings() : ModuleSettings(moduleName) { + +} + +} +} +} diff --git a/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.h b/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.h new file mode 100644 index 0000000000..08ad112aba --- /dev/null +++ b/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.h @@ -0,0 +1,21 @@ +#pragma once + +#include "storm/settings/modules/ModuleSettings.h" + +namespace storm { +namespace settings { +namespace modules { + +class GenerateMonitorVerifierSettings : public ModuleSettings { + public: + GenerateMonitorVerifierSettings(); + + virtual ~GenerateMonitorVerifierSettings() = default; + + // The name of the module. + static const std::string moduleName; +}; + +} // namespace modules +} // namespace settings +} // namespace storm diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp new file mode 100644 index 0000000000..0b7c3b43e4 --- /dev/null +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -0,0 +1,196 @@ +#include "storm-pomdp/generator/GenerateMonitorVerifier.h" +#include "storm/api/builder.h" + +namespace storm { +namespace generator { + +template +GenerateMonitorVerifier::GenerateMonitorVerifier(models::sparse::Dtmc const& mc, models::sparse::Mdp const& monitor, + Options const& options) + : mc(mc), monitor(monitor), options(options) {} + +template +std::shared_ptr> GenerateMonitorVerifier::createProduct() { + typedef storm::storage::sparse::state_type state_type; + typedef std::pair product_state_type; + + const std::set& actions = monitor.getChoiceLabeling().getLabels(); + + uint32_t nextObservation = 0; + std::map, uint32_t> observationMap; + std::vector observations; + + std::map> actionMap; + for (auto const& action : actions) { + actionMap[action]; + } + actionMap["end"]; + + storm::storage::SparseMatrixBuilder builder(0, 0, 0, false, true, 0); + std::size_t currentRow = 0; + state_type nextStateId = 0; + + state_type goalIndex = nextStateId++; + builder.newRowGroup(currentRow); + actionMap["end"].push_back(currentRow); + builder.addDiagonalEntry(currentRow++, utility::one()); + observations.push_back(nextObservation++); + + state_type stopIndex = nextStateId++; + builder.newRowGroup(currentRow); + actionMap["end"].push_back(currentRow); + builder.addDiagonalEntry(currentRow++, utility::one()); + observations.push_back(nextObservation++); + + std::map prodToIndexMap; + std::vector prodInitial; + + std::deque todo; + for (state_type mc_s_0 : mc.getInitialStates()) { + for (state_type mon_s_0 : monitor.getInitialStates()) { + product_state_type prod_s(mon_s_0, mc_s_0); + state_type index = nextStateId++; + prodToIndexMap[prod_s] = index; + prodInitial.push_back(index); + todo.push_back(prod_s); + } + } + + while (!todo.empty()) { + auto const [mc_from, mon_from] = std::move(todo.front()); + todo.pop_front(); + + // Set observations for from + bool accepting = monitor.getStateLabeling().getStateHasLabel(options.acceptingLabel, mon_from); + uint32_t step; + for (auto& label : monitor.getStateLabeling().getLabelsOfState(mon_from)) { + if (label.starts_with(options.stepPrefix)) { + step = std::stoi(label.substr(options.stepPrefix.length())); + } + } + std::pair obsPair(step, accepting); + if (!observationMap.contains(obsPair)) { + observationMap[obsPair] = nextObservation++; + } + observations.push_back(observationMap.at(obsPair)); + + // Set transitions for from and add new states to todo + builder.newRowGroup(currentRow); + if (monitor.getStateLabeling().getLabelsOfState(mon_from).contains(options.horizonLabel)) { + for (const auto& action : actions) { + for (state_type initState : prodInitial) { + builder.addNextValue(currentRow, initState, storm::utility::one() / prodInitial.size()); + } + actionMap[action].push_back(currentRow); + currentRow++; + } + } else { + std::size_t numMonRows = monitor.getTransitionMatrix().getRowGroupSize(mon_from); + std::set actionsNotTaken(actions); + for (std::size_t i = 0; i < numMonRows; i++) { + // Remove labels of monitor choice from the labels we still have to take + STORM_LOG_ASSERT(monitor.getChoiceLabeling().getLabelsOfChoice(mon_from + i).size() == 1, "Monitor choice has not exactly one choice label"); + const auto action = *monitor.getChoiceLabeling().getLabelsOfChoice(mon_from + i).begin(); + actionsNotTaken.erase(action); + + const auto& monitorRow = monitor.getTransitionMatrix().getRow(mon_from, i); + STORM_LOG_ASSERT(monitorRow.getNumberOfEntries() == 1, "Monitor is not fully deterministic in"); + const auto& monitorEntry = monitorRow.begin(); + + const auto& mcRow = mc.getTransitionMatrix().getRow(mc_from); + + // Find total probability of the transitions to a state with label action + auto totalProbability = utility::zero(); + for (const auto& mcEntry : mcRow) { + if (mc.getStateLabeling().getStateHasLabel(action, mcEntry.getColumn())) { + totalProbability += mcEntry.getValue(); + } + } + + // Add new entries to an unsorted vector containing possible duplicate indexes + std::map newRow; + + // Direct probability not used towards the initial states + if (totalProbability < storm::utility::one()) { + for (state_type initState : prodInitial) { + if (newRow.contains(initState)) + newRow[initState] = newRow[initState] + (1 - totalProbability) / prodInitial.size(); + else + newRow[initState] = (1 - totalProbability) / prodInitial.size(); + } + } + + // Add transitions to the successors, if the successor has not yet been added, add it to the todo list + for (const auto& mcEntry : mcRow) { + if (mc.getStateLabeling().getStateHasLabel(action, mcEntry.getColumn())) { + const product_state_type to_pair(mcEntry.getColumn(), monitorEntry->getColumn()); + state_type indexTo; + if (auto it = prodToIndexMap.find(to_pair); it != prodToIndexMap.end()) { + indexTo = it->second; + } else { + indexTo = nextStateId++; + todo.push_back(to_pair); + prodToIndexMap[to_pair] = indexTo; + } + if (newRow.contains(indexTo)) + newRow[indexTo] = newRow[indexTo] + mcEntry.getValue(); + else + newRow[indexTo] = mcEntry.getValue(); + } + } + + // Insert new entries + for (const auto& entry : newRow) { + builder.addNextValue(currentRow, entry.first, entry.second); + } + actionMap[action].push_back(currentRow); + currentRow++; + } + + for (const auto& action : actionsNotTaken) { + for (state_type initState : prodInitial) { + builder.addNextValue(currentRow, initState, storm::utility::one() / prodInitial.size()); + } + actionMap[action].push_back(currentRow); + currentRow++; + } + } + + if (monitor.getStateLabeling().getStateHasLabel(options.acceptingLabel, mon_from)) { + if (mc.getStateLabeling().getStateHasLabel(options.goodLabel, mc_from)) { + builder.addNextValue(currentRow, goalIndex, utility::one()); + } else { + builder.addNextValue(currentRow, stopIndex, utility::one()); + } + actionMap["end"].push_back(currentRow); + currentRow++; + } + } + + const state_type numberOfStates = nextStateId; + storm::models::sparse::StateLabeling stateLabeling(numberOfStates); + stateLabeling.addLabel("init", storm::storage::BitVector(numberOfStates, prodInitial.begin(), prodInitial.end())); + + stateLabeling.addLabel("goal", storm::storage::BitVector(numberOfStates)); + stateLabeling.addLabelToState("goal", goalIndex); + + stateLabeling.addLabel("stop", storm::storage::BitVector(numberOfStates)); + stateLabeling.addLabelToState("stop", stopIndex); + + const size_t numberOfRows = currentRow; + storm::models::sparse::ChoiceLabeling choiceLabeling(numberOfRows); + for (const auto& [label, vec] : actionMap) { + choiceLabeling.addLabel(label, storm::storage::BitVector(numberOfRows, vec.begin(), vec.end())); + } + + storm::storage::sparse::ModelComponents components(builder.build(), stateLabeling); + components.observabilityClasses = observations; + components.choiceLabeling = choiceLabeling; + return std::make_shared>(std::move(components)); +} + +template class GenerateMonitorVerifier; +template class GenerateMonitorVerifier; + +} // namespace generator +} // namespace storm diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.h b/src/storm-pomdp/generator/GenerateMonitorVerifier.h new file mode 100644 index 0000000000..dc256f89ae --- /dev/null +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.h @@ -0,0 +1,25 @@ +#pragma once +#include "storm/models/sparse/Dtmc.h" +#include "storm/models/sparse/Pomdp.h" + +namespace storm::generator { + +template +class GenerateMonitorVerifier { + public: + struct Options { + std::string goodLabel = "good"; + std::string acceptingLabel = "accepting"; + std::string stepPrefix = "step"; + std::string horizonLabel = "horizon"; + }; + GenerateMonitorVerifier(storm::models::sparse::Dtmc const& mc, storm::models::sparse::Mdp const& monitor, Options const& options); + std::shared_ptr> createProduct(); + + private: + const storm::models::sparse::Dtmc& mc; + const storm::models::sparse::Mdp& monitor; + Options options; +}; + +} // namespace storm::generator \ No newline at end of file diff --git a/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp b/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp index d6fed4ac45..f18b08ad46 100644 --- a/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp +++ b/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp @@ -382,6 +382,7 @@ NondeterministicBeliefTracker::NondeterministicBeliefTra template bool NondeterministicBeliefTracker::reset(uint32_t observation) { + beliefs = std::unordered_set(); bool hit = false; for (auto state : pomdp.getInitialStates()) { if (observation == pomdp.getObservation(state)) { From 3a8df49c11eec68e918c129290f39751f500bcc0 Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Mon, 11 Nov 2024 23:17:11 +0100 Subject: [PATCH 003/102] update the observation trace unfolder towards generic support to compute conditional probs and fix bug in belief tracker --- .../NondeterministicBeliefTracker.cpp | 4 +- .../transformer/ObservationTraceUnfolder.cpp | 67 +++++++++++++------ .../transformer/ObservationTraceUnfolder.h | 14 +++- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp b/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp index d6fed4ac45..792ef0ebbf 100644 --- a/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp +++ b/src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp @@ -383,6 +383,7 @@ NondeterministicBeliefTracker::NondeterministicBeliefTra template bool NondeterministicBeliefTracker::reset(uint32_t observation) { bool hit = false; + beliefs.clear(); for (auto state : pomdp.getInitialStates()) { if (observation == pomdp.getObservation(state)) { hit = true; @@ -492,9 +493,6 @@ bool NondeterministicBeliefTracker::hasTimedOut() const template class SparseBeliefState; template bool operator==(SparseBeliefState const&, SparseBeliefState const&); template class NondeterministicBeliefTracker>; -// template class ObservationDenseBeliefState; -// template bool operator==(ObservationDenseBeliefState const&, ObservationDenseBeliefState const&); -// template class NondeterministicBeliefTracker>; template class SparseBeliefState; template bool operator==(SparseBeliefState const&, SparseBeliefState const&); diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index a6f834542c..95bffc752e 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -1,9 +1,10 @@ #include "storm-pomdp/transformer/ObservationTraceUnfolder.h" + +#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidArgumentException.h" #include "storm/storage/expressions/ExpressionManager.h" #include "storm/utility/ConstantsComparator.h" -#include "storm/adapters/RationalFunctionAdapter.h" #undef _VERBOSE_OBSERVATION_UNFOLDING @@ -11,13 +12,15 @@ namespace storm { namespace pomdp { template ObservationTraceUnfolder::ObservationTraceUnfolder(storm::models::sparse::Pomdp const& model, std::vector const& risk, - std::shared_ptr& exprManager) - : model(model), risk(risk), exprManager(exprManager) { + std::shared_ptr& exprManager, + ObservationTraceUnfolderOptions const& options) + : model(model), risk(risk), exprManager(exprManager), options(options) { statesPerObservation = std::vector(model.getNrObservations() + 1, storm::storage::BitVector(model.getNumberOfStates())); for (uint64_t state = 0; state < model.getNumberOfStates(); ++state) { statesPerObservation[model.getObservation(state)].set(state, true); } svvar = exprManager->declareFreshIntegerVariable(false, "_s"); + tsvar = exprManager->declareFreshIntegerVariable(false, "_t"); } template @@ -25,6 +28,7 @@ std::shared_ptr> ObservationTraceUnfolder< std::vector modifiedObservations = observations; // First observation should be special. // This just makes the algorithm simpler because we do not treat the first step as a special case later. + // We overwrite the observation with a non-existing obs z* modifiedObservations[0] = model.getNrObservations(); storm::storage::BitVector initialStates = model.getInitialStates(); @@ -36,7 +40,7 @@ std::shared_ptr> ObservationTraceUnfolder< } STORM_LOG_THROW(actualInitialStates.getNumberOfSetBits() == 1, storm::exceptions::InvalidArgumentException, "Must have unique initial state matching the observation"); - // + // For this z* that only exists in the initial state, we now also define the states for this observation. statesPerObservation[model.getNrObservations()] = actualInitialStates; #ifdef _VERBOSE_OBSERVATION_UNFOLDING @@ -44,7 +48,9 @@ std::shared_ptr> ObservationTraceUnfolder< #endif storm::storage::sparse::StateValuationsBuilder svbuilder; svbuilder.addVariable(svvar); + svbuilder.addVariable(tsvar); + // TODO: Do we need this as ordered maps? Is it better to make them unordered? std::map unfoldedToOld; std::map unfoldedToOldNextStep; std::map oldToUnfolded; @@ -53,15 +59,30 @@ std::shared_ptr> ObservationTraceUnfolder< std::cout << "start buildiing matrix...\n"; #endif + uint64_t newStateIndex = 0; + // TODO do not add violated state if we do rejection sampling. + uint64_t violatedState = newStateIndex; + ++newStateIndex; // Add this initial state state: - unfoldedToOldNextStep[0] = actualInitialStates.getNextSetIndex(0); + uint64_t initialState = newStateIndex; + ++newStateIndex; + unfoldedToOldNextStep[initialState] = actualInitialStates.getNextSetIndex(0); + + uint64_t resetDestination = options.rejectionSampling ? initialState : violatedState; // Should be initial state for the standard semantics. storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, true, true); - uint64_t newStateIndex = 1; - uint64_t newRowGroupStart = 0; - uint64_t newRowCount = 0; - // Notice that we are going to use a special last step + // TODO only add this state if it is actually reachable / rejection sampling + // the violated state is a sink state + transitionMatrixBuilder.newRowGroup(violatedState); + transitionMatrixBuilder.addNextValue(violatedState, violatedState, storm::utility::one()); + svbuilder.addState(violatedState, {}, {-1, -1}); + + // Now we are starting to build the MDP from the initial state onwards. + uint64_t newRowGroupStart = initialState; + uint64_t newRowCount = initialState; + + // Notice that we are going to use a special last step for (uint64_t step = 0; step < observations.size() - 1; ++step) { oldToUnfolded.clear(); unfoldedToOld = unfoldedToOldNextStep; @@ -73,7 +94,7 @@ std::shared_ptr> ObservationTraceUnfolder< std::cout << "\tconsider new state " << unfoldedToOldEntry.first << '\n'; #endif assert(step == 0 || newRowCount == transitionMatrixBuilder.getLastRow() + 1); - svbuilder.addState(unfoldedToOldEntry.first, {}, {static_cast(unfoldedToOldEntry.second)}); + svbuilder.addState(unfoldedToOldEntry.first, {}, {static_cast(unfoldedToOldEntry.second), static_cast(step)}); uint64_t oldRowIndexStart = model.getNondeterministicChoiceIndices()[unfoldedToOldEntry.second]; uint64_t oldRowIndexEnd = model.getNondeterministicChoiceIndices()[unfoldedToOldEntry.second + 1]; @@ -96,7 +117,7 @@ std::shared_ptr> ObservationTraceUnfolder< // Add the resets if (resetProb != storm::utility::zero()) { - transitionMatrixBuilder.addNextValue(newRowCount, 0, resetProb); + transitionMatrixBuilder.addNextValue(newRowCount, resetDestination, resetProb); } #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << "\t\t\t add other transitions...\n"; @@ -125,22 +146,20 @@ std::shared_ptr> ObservationTraceUnfolder< } newRowCount++; } - newRowGroupStart = transitionMatrixBuilder.getLastRow() + 1; } } // Now, take care of the last step. uint64_t sinkState = newStateIndex; uint64_t targetState = newStateIndex + 1; - auto cc = storm::utility::ConstantsComparator(); + [[maybe_unused]] auto cc = storm::utility::ConstantsComparator(); for (auto const& unfoldedToOldEntry : unfoldedToOldNextStep) { - svbuilder.addState(unfoldedToOldEntry.first, {}, {static_cast(unfoldedToOldEntry.second)}); + svbuilder.addState(unfoldedToOldEntry.first, {}, {static_cast(unfoldedToOldEntry.second), static_cast(observations.size() - 1)}); transitionMatrixBuilder.newRowGroup(newRowGroupStart); STORM_LOG_ASSERT(risk.size() > unfoldedToOldEntry.second, "Must be a state"); STORM_LOG_ASSERT(!cc.isLess(storm::utility::one(), risk[unfoldedToOldEntry.second]), "Risk must be a probability"); STORM_LOG_ASSERT(!cc.isLess(risk[unfoldedToOldEntry.second], storm::utility::zero()), "Risk must be a probability"); - // std::cout << "risk is" << risk[unfoldedToOldEntry.second] << '\n'; if (!storm::utility::isOne(risk[unfoldedToOldEntry.second])) { transitionMatrixBuilder.addNextValue(newRowGroupStart, sinkState, storm::utility::one() - risk[unfoldedToOldEntry.second]); } @@ -152,13 +171,13 @@ std::shared_ptr> ObservationTraceUnfolder< // sink state transitionMatrixBuilder.newRowGroup(newRowGroupStart); transitionMatrixBuilder.addNextValue(newRowGroupStart, sinkState, storm::utility::one()); - svbuilder.addState(sinkState, {}, {-1}); + svbuilder.addState(sinkState, {}, {-1, -1}); newRowGroupStart++; transitionMatrixBuilder.newRowGroup(newRowGroupStart); // target state transitionMatrixBuilder.addNextValue(newRowGroupStart, targetState, storm::utility::one()); - svbuilder.addState(targetState, {}, {-1}); + svbuilder.addState(targetState, {}, {-1, -1}); #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << "build matrix...\n"; #endif @@ -168,14 +187,19 @@ std::shared_ptr> ObservationTraceUnfolder< #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << components.transitionMatrix << '\n'; #endif - STORM_LOG_ASSERT(components.transitionMatrix.getRowGroupCount() == targetState + 1, + STORM_LOG_ASSERT(components.transitionMatrix.getRowGroupCount() == targetState + 2, "Expect row group count (" << components.transitionMatrix.getRowGroupCount() << ") one more as target state index " << targetState << ")"); storm::models::sparse::StateLabeling labeling(components.transitionMatrix.getRowGroupCount()); labeling.addLabel("_goal"); labeling.addLabelToState("_goal", targetState); + labeling.addLabel("_violated"); + labeling.addLabelToState("_violated", violatedState); + labeling.addLabel("_end"); + labeling.addLabelToState("_end", sinkState); + labeling.addLabelToState("_end", targetState); labeling.addLabel("init"); - labeling.addLabelToState("init", 0); + labeling.addLabelToState("init", initialState); components.stateLabeling = labeling; components.stateValuations = svbuilder.build(); return std::make_shared>(std::move(components)); @@ -192,6 +216,11 @@ void ObservationTraceUnfolder::reset(uint32_t observation) { traceSoFar = {observation}; } +template +bool ObservationTraceUnfolder::isRejectionSamplingSet() const { + return options.rejectionSampling; +} + template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h index 9381c3c79d..c5b2c6625b 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h @@ -2,6 +2,12 @@ namespace storm { namespace pomdp { + +class ObservationTraceUnfolderOptions { + public: + bool rejectionSampling = true; +}; + /** * Observation-trace unrolling to allow model checking for monitoring. * This approach is outlined in Junges, Hazem, Seshia -- Runtime Monitoring for Markov Decision Processes @@ -17,7 +23,7 @@ class ObservationTraceUnfolder { * @param exprManager an Expression Manager */ ObservationTraceUnfolder(storm::models::sparse::Pomdp const& model, std::vector const& risk, - std::shared_ptr& exprManager); + std::shared_ptr& exprManager, ObservationTraceUnfolderOptions const& options); /** * Transform in one shot * @param observations @@ -36,13 +42,17 @@ class ObservationTraceUnfolder { */ void reset(uint32_t observation); + bool isRejectionSamplingSet() const; + private: storm::models::sparse::Pomdp const& model; std::vector risk; // TODO reconsider holding this as a reference, but there were some strange bugs std::shared_ptr& exprManager; std::vector statesPerObservation; std::vector traceSoFar; - storm::expressions::Variable svvar; + storm::expressions::Variable svvar; // Maps to the old state (explicit encoding) + storm::expressions::Variable tsvar; // Maps to the time step + ObservationTraceUnfolderOptions options; }; } // namespace pomdp From 561ca9ff4b8273cf9130c1e41c254778a8588478 Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Mon, 11 Nov 2024 23:22:31 +0100 Subject: [PATCH 004/102] format --- src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index 95bffc752e..7db1e2e833 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -5,7 +5,6 @@ #include "storm/storage/expressions/ExpressionManager.h" #include "storm/utility/ConstantsComparator.h" - #undef _VERBOSE_OBSERVATION_UNFOLDING namespace storm { From bbb63a7601662f75a477ee6d08bd29d49ebba054 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 12 Nov 2024 13:41:08 +0100 Subject: [PATCH 005/102] Add verimon storm code --- .../generator/GenerateMonitorVerifier.cpp | 110 +++++++++++++++++- .../generator/GenerateMonitorVerifier.h | 16 ++- 2 files changed, 120 insertions(+), 6 deletions(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index 0b7c3b43e4..511cbe180e 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -1,16 +1,36 @@ #include "storm-pomdp/generator/GenerateMonitorVerifier.h" + +#include +#include "storm/adapters/RationalNumberAdapter.h" #include "storm/api/builder.h" namespace storm { namespace generator { +template +MonitorVerifier::MonitorVerifier(const models::sparse::Pomdp& product, + const std::map, uint32_t>& observationMap) + : product(storm::models::sparse::Pomdp(product)), observationMap(observationMap) { + std::cout << "copying" << std::endl; +} + +template +const std::map, uint32_t>& MonitorVerifier::getObservationMap() { + return observationMap; +} + +template +const models::sparse::Pomdp& MonitorVerifier::getProduct() { + return product; +} + template GenerateMonitorVerifier::GenerateMonitorVerifier(models::sparse::Dtmc const& mc, models::sparse::Mdp const& monitor, Options const& options) : mc(mc), monitor(monitor), options(options) {} template -std::shared_ptr> GenerateMonitorVerifier::createProduct() { +std::shared_ptr> GenerateMonitorVerifier::createProduct() { typedef storm::storage::sparse::state_type state_type; typedef std::pair product_state_type; @@ -167,6 +187,7 @@ std::shared_ptr> GenerateMonitorVerifier } } + // Create state labeling const state_type numberOfStates = nextStateId; storm::models::sparse::StateLabeling stateLabeling(numberOfStates); stateLabeling.addLabel("init", storm::storage::BitVector(numberOfStates, prodInitial.begin(), prodInitial.end())); @@ -177,18 +198,97 @@ std::shared_ptr> GenerateMonitorVerifier stateLabeling.addLabel("stop", storm::storage::BitVector(numberOfStates)); stateLabeling.addLabelToState("stop", stopIndex); + // Add choice labeling const size_t numberOfRows = currentRow; storm::models::sparse::ChoiceLabeling choiceLabeling(numberOfRows); for (const auto& [label, vec] : actionMap) { choiceLabeling.addLabel(label, storm::storage::BitVector(numberOfRows, vec.begin(), vec.end())); } - storm::storage::sparse::ModelComponents components(builder.build(), stateLabeling); - components.observabilityClasses = observations; - components.choiceLabeling = choiceLabeling; - return std::make_shared>(std::move(components)); + // Add state valuations + storm::storage::sparse::StateValuationsBuilder svBuilder; + std::set variables; + for (auto i = 0; i < mc.getNumberOfStates(); i++) { + const auto& valAssignment = mc.getStateValuations().at(i); + for (auto val = valAssignment.begin(); val != valAssignment.end(); ++val) { + if (val.isVariableAssignment() && !variables.contains(val.getVariable())) { + variables.emplace(val.getVariable()); + svBuilder.addVariable(val.getVariable()); + } + } + } + + for (auto i = 0; i < mc.getNumberOfStates(); i++) { + for (auto j = 0; j < monitor.getNumberOfStates(); j++) { + product_state_type s(i, j); + if (!prodToIndexMap.contains(s)) + continue; + + std::vector booleanValues; + std::vector integerValues; + std::vector rationalValues; + + const auto& valAssignment = mc.getStateValuations().at(i); + + for (auto& var : variables) { + for (auto val = valAssignment.begin(); val != valAssignment.end(); ++val) { + if (var == val.getVariable()) { + if (val.isBoolean()) { + booleanValues.push_back(val.getBooleanValue()); + } else if (val.isInteger()) { + integerValues.push_back(val.getIntegerValue()); + } else if (val.isRational()) { + rationalValues.push_back(val.getRationalValue()); + } + break; + } + } + } + svBuilder.addState(prodToIndexMap[std::make_pair(i, j)], std::move(booleanValues), std::move(integerValues), std::move(rationalValues)); + } + } + + std::vector goalBooleanValues; + std::vector goalIntegerValues; + std::vector goalRationalValues; + for (auto& var : variables) { + if (var.hasBooleanType()) { + goalBooleanValues.push_back(false); + } else if (var.hasIntegerType()) { + goalIntegerValues.push_back(-1); + } else if (var.hasRationalType()) { + goalRationalValues.emplace_back(-1); + } + } + svBuilder.addState(goalIndex, std::move(goalBooleanValues), std::move(goalIntegerValues), std::move(goalRationalValues)); + + std::vector stopBooleanValues; + std::vector stopIntegerValues; + std::vector stopRationalValues; + for (auto& var : variables) { + if (var.hasBooleanType()) { + stopBooleanValues.push_back(false); + } else if (var.hasIntegerType()) { + stopIntegerValues.push_back(-1); + } else if (var.hasRationalType()) { + stopRationalValues.emplace_back(-1); + } + } + svBuilder.addState(stopIndex, std::move(stopBooleanValues), std::move(stopIntegerValues), std::move(stopRationalValues)); + + // Build model + storm::storage::sparse::ModelComponents components(builder.build(), std::move(stateLabeling)); + components.observabilityClasses = std::move(observations); + components.choiceLabeling = std::move(choiceLabeling); + components.stateValuations = svBuilder.build(); + storm::models::sparse::Pomdp product(std::move(components)); + auto mv = std::make_shared>(std::move(product), std::move(observationMap)); + std::cout << mv->getProduct().getNrObservations() << std::endl; + return mv; } +template class MonitorVerifier; +template class MonitorVerifier; template class GenerateMonitorVerifier; template class GenerateMonitorVerifier; diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.h b/src/storm-pomdp/generator/GenerateMonitorVerifier.h index dc256f89ae..62bb1e74dc 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.h +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.h @@ -1,9 +1,23 @@ #pragma once #include "storm/models/sparse/Dtmc.h" +#include "storm/models/sparse/Mdp.h" #include "storm/models/sparse/Pomdp.h" namespace storm::generator { +template +class MonitorVerifier { + public: + MonitorVerifier(const storm::models::sparse::Pomdp& product, const std::map, uint32_t>& observationMap); + + const std::map, uint32_t>& getObservationMap(); + const storm::models::sparse::Pomdp& getProduct(); + + private: + storm::models::sparse::Pomdp product; + std::map, uint32_t> observationMap; +}; + template class GenerateMonitorVerifier { public: @@ -14,7 +28,7 @@ class GenerateMonitorVerifier { std::string horizonLabel = "horizon"; }; GenerateMonitorVerifier(storm::models::sparse::Dtmc const& mc, storm::models::sparse::Mdp const& monitor, Options const& options); - std::shared_ptr> createProduct(); + std::shared_ptr> createProduct(); private: const storm::models::sparse::Dtmc& mc; From e81617330edbd7f3484137ce3ccb29f6c769bd7b Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 14 Nov 2024 10:20:45 +0100 Subject: [PATCH 006/102] Add instantiation of observation trace unfolder for intervals --- src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index 7db1e2e833..8ee227c5e4 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -186,7 +186,7 @@ std::shared_ptr> ObservationTraceUnfolder< #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << components.transitionMatrix << '\n'; #endif - STORM_LOG_ASSERT(components.transitionMatrix.getRowGroupCount() == targetState + 2, + STORM_LOG_ASSERT(components.transitionMatrix.getRowGroupCount() == targetState + 1, "Expect row group count (" << components.transitionMatrix.getRowGroupCount() << ") one more as target state index " << targetState << ")"); storm::models::sparse::StateLabeling labeling(components.transitionMatrix.getRowGroupCount()); @@ -221,6 +221,7 @@ bool ObservationTraceUnfolder::isRejectionSamplingSet() const { } template class ObservationTraceUnfolder; +template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; } // namespace pomdp From 58e7ceeddaaf4c0ed5d5853cf9117ccd482d927d Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sun, 17 Nov 2024 07:21:57 +0100 Subject: [PATCH 007/102] Re-implementation of restart method for conditional probabilities for MDPs --- .../helper/conditional/ConditionalHelper.cpp | 282 ++++++++++++++++++ .../helper/conditional/ConditionalHelper.h | 30 ++ .../prctl/SparseMdpPrctlModelChecker.cpp | 12 +- .../settings/modules/ModelCheckerSettings.cpp | 11 + .../settings/modules/ModelCheckerSettings.h | 3 + 5 files changed, 334 insertions(+), 4 deletions(-) create mode 100644 src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp create mode 100644 src/storm/modelchecker/helper/conditional/ConditionalHelper.h diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp new file mode 100644 index 0000000000..9d4676a8e2 --- /dev/null +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -0,0 +1,282 @@ +#include "storm/modelchecker/helper/conditional/ConditionalHelper.h" + +#include "storm/adapters/RationalNumberAdapter.h" +#include "storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h" +#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" +#include "storm/solver/SolveGoal.h" +#include "storm/storage/BitVector.h" +#include "storm/storage/MaximalEndComponentDecomposition.h" +#include "storm/storage/SparseMatrix.h" +#include "storm/transformer/EndComponentEliminator.h" +#include "storm/utility/graph.h" +#include "storm/utility/macros.h" + +#include "storm/exceptions/NotImplementedException.h" +#include "storm/exceptions/NotSupportedException.h" + +#include "storm/settings/SettingsManager.h" +#include "storm/settings/modules/ModelCheckerSettings.h" + +namespace storm::modelchecker { + +namespace internal { + +template +SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix&& matrix, std::vector&& rowValues, + storm::OptionalRef const& rowsWithSum1, storm::solver::OptimizationDirection const dir, + uint64_t const initialState) { + if (rowsWithSum1.has_value()) { + storm::storage::BitVector const allRowGroups(matrix.getRowGroupCount(), true); + storm::storage::BitVector const noRowGroups(matrix.getRowGroupCount(), false); + storm::storage::MaximalEndComponentDecomposition mecs(matrix, matrix.transpose(true), allRowGroups, *rowsWithSum1); + if (!mecs.empty()) { + auto ecElimResult = storm::transformer::EndComponentEliminator::transform(matrix, mecs, allRowGroups, noRowGroups); + std::vector newRowValues; + newRowValues.reserve(ecElimResult.newToOldRowMapping.size()); + for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { + newRowValues.push_back(rowValues[oldRowIndex]); + } + return solveMinMaxEquationSystem(env, std::move(ecElimResult.matrix), std::move(newRowValues), storm::NullRef, dir, + ecElimResult.oldToNewStateMapping[initialState]); + } + } + + // Initialize the solution vector. + std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); + + // Set up the solver. + auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create( + env, std::forward>(matrix)); + solver->setOptimizationDirection(dir); + solver->setRequirementsChecked(); + solver->setHasUniqueSolution(true); + solver->setHasNoEndComponents(true); + solver->setLowerBound(storm::utility::zero()); + solver->setUpperBound(storm::utility::one()); + + // Solve the corresponding system of equations. + solver->solveEquations(env, x, rowValues); + return x[initialState]; +} + +/*! + * Computes the reachability probabilities for the given target states and inserts all non-zero values into the given map. + * The assumption is that usually, not all states are reachable from the initial states. + */ +template +void computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, + storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { + if (initialStates.empty()) { // nothing to do + return; + } + auto const reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, allowedStates, targetStates); + auto const subTargets = targetStates % reachableStates; + // Catch the case where no target is reachable from an initial state. In this case, there is nothing to do since all probabilities are zero. + if (subTargets.empty()) { + return; + } + auto const subInits = initialStates % reachableStates; + auto const submatrix = transitionMatrix.getSubmatrix(true, reachableStates, reachableStates); + // TODO: adapt precision in sound mode + auto const subResult = helper::SparseMdpPrctlHelper::computeUntilProbabilities( + env, storm::solver::SolveGoal(dir, subInits), submatrix, submatrix.transpose(true), storm::storage::BitVector(subTargets.size(), true), + subTargets, false, false); + auto origInitIt = initialStates.begin(); + for (auto subInit : subInits) { + auto const& val = subResult.values[subInit]; + if (!storm::utility::isZero(val)) { + nonZeroResults.emplace(*origInitIt, val); + } + ++origInitIt; + } +} + +template +struct NormalFormData { + storm::storage::BitVector const + definedStates; // Those states where the property is defined, i.e., the condition states can be reached with positive probability + storm::storage::BitVector const terminalStates; // Those states where we already know the probability to reach the condition and the target value + storm::storage::BitVector const conditionStates; // Those states where the condition holds almost surely (under all schedulers) + storm::storage::BitVector const observationFailureStates; // Those states where the condition is not reachable (under all schedulers) + std::map const nonZeroTargetStateValues; // The known non-zero target values. (default is zero) + // There are three cases of terminal states: + // 1. conditionStates: The condition holds, so the target value is the optimal probability to reach target from there + // 2. targetStates: The target is reached, so the target value is the optimal probability to reach a condition from there. + // The remaining probability mass is the probability of an observation failure + // 3. states that can not reach the condition under any scheduler. The target value is zero. + + // TerminalStates is a superset of conditionStates and dom(nonZeroTargetStateValues). + // For a terminalState that is not a conditionState, it is impossible to (reach the condition and not reach the target). + + ValueType targetValue(uint64_t state) const { + STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get target value for non-terminal state"); + auto const it = nonZeroTargetStateValues.find(state); + return it == nonZeroTargetStateValues.end() ? storm::utility::zero() : it->second; + } + + ValueType failProbability(uint64_t state) const { + STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get fail probability for non-terminal state"); + STORM_LOG_ASSERT(!conditionStates.get(state), "Tried to get fail probability for a condition state"); + // condition states have fail probability zero + return storm::utility::one() - targetValue(state); + } +}; + +template +NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, + storm::storage::BitVector const& conditionStates) { + storm::storage::BitVector const allStates(transitionMatrix.getRowGroupCount(), true); + auto extendedConditionStates = + storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); + auto observationFailureStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); + std::map nonZeroTargetStateValues; + auto const extendedTargetStates = + storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, targetStates); + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); + auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | observationFailureStates); + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + + auto terminalStates = extendedConditionStates | extendedTargetStates | observationFailureStates; + + if (storm::solver::minimize(dir)) { + // There can be targetAndNotCondFailStates from which only the *minimal* probability to reach a condition is zero. + // For those states, the optimal policy is to enforce observation failure. + // States that can only reach (target states with almost sure observation failure) or observation failure will be treated as terminal states with + // targetValue zero and failProbability one. + + // We first determine states where the optimal policy reaches the condition with positive probability + auto terminalStatesThatReachCondition = extendedConditionStates; + for (auto state : targetAndNotCondFailStates) { + if (nonZeroTargetStateValues.contains(state)) { + terminalStatesThatReachCondition.set(state, true); + } + } + // Then, we determine the non-terminal states that cannot reach such states. + terminalStates |= storm::utility::graph::performProb0A(backwardTransitions, ~terminalStates, terminalStatesThatReachCondition); + } + + return NormalFormData{.terminalStates = std::move(terminalStates), + .conditionStates = std::move(extendedConditionStates), + .observationFailureStates = std::move(observationFailureStates), + .nonZeroTargetStateValues = std::move(nonZeroTargetStateValues)}; +} + +/*! + * Uses the restart method by Baier et al. +// @see doi.org/10.1007/978-3-642-54862-8_43 + */ +template +SolutionType computeViaRestartMethod(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { + auto const maybeStates = ~normalForm.terminalStates; + auto const stateToMatrixIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); + auto const numMaybeStates = maybeStates.getNumberOfSetBits(); + auto const numMaybeChoices = transitionMatrix.getNumRowsInRowGroups(maybeStates); + + // Build the transitions that include a backwards loop to the initial state + storm::storage::SparseMatrixBuilder matrixBuilder(numMaybeChoices, numMaybeStates, 0, true, true, numMaybeStates); + std::vector rowValues; + storm::storage::BitVector rowsWithSum1(numMaybeChoices, true); + rowValues.reserve(numMaybeChoices); + uint64_t currentRow = 0; + for (auto state : maybeStates) { + matrixBuilder.newRowGroup(currentRow); + for (auto origRowIndex : transitionMatrix.getRowGroupIndices(state)) { + // We make two passes over the successors. First, we find out the reset probabilities and target probabilities + // Then, we insert the matrix entries in the correct order + // This two-phase approach is to avoid a costly out-of-order insertion into the matrix + ValueType targetProbability = storm::utility::zero(); + ValueType restartProbability = storm::utility::zero(); + bool rowSumIsLess1 = false; + for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { + if (normalForm.terminalStates.get(entry.getColumn())) { + ValueType const targetValue = normalForm.targetValue(entry.getColumn()); + targetProbability += targetValue * entry.getValue(); + if (normalForm.conditionStates.get(entry.getColumn())) { + rowSumIsLess1 = true; + } else { + if (!storm::utility::isZero(targetValue)) { + rowSumIsLess1 = true; + } + restartProbability += entry.getValue() * normalForm.failProbability(entry.getColumn()); + } + } + } + if (rowSumIsLess1) { + rowsWithSum1.set(currentRow, false); + } + rowValues.push_back(targetProbability); + bool addRestartTransition = !storm::utility::isZero(restartProbability); + for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { + // Insert backloop probability if we haven't done so yet and are past the initial state index + // This is to avoid a costly out-of-order insertion into the matrix + if (addRestartTransition && entry.getColumn() > initialState) { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[initialState], restartProbability); + addRestartTransition = false; + } + if (maybeStates.get(entry.getColumn())) { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[entry.getColumn()], entry.getValue()); + } + } + // Add the backloop if we haven't done this already + if (addRestartTransition) { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[initialState], restartProbability); + } + ++currentRow; + } + } + + return solveMinMaxEquationSystem(env, matrixBuilder.build(), std::move(rowValues), rowsWithSum1, dir, stateToMatrixIndexMap[initialState]); +} + +} // namespace internal + +template +std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { + // We first translate the problem into a normal form. + // @see doi.org/10.1007/978-3-642-54862-8_43 + STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, + "Only one initial state is supported for conditional probabilities"); + auto normalFormData = internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, targetStates, conditionStates); + + // Then, we solve the induced problem using the selected algorithm. + auto const initialState = *goal.relevantValues().begin(); + ValueType initialStateValue = -storm::utility::one(); + auto const algString = storm::settings::getModule().getConditionalAlgorithm(); + if (normalFormData.terminalStates.get(initialState)) { + if (normalFormData.conditionStates.get(initialState)) { + initialStateValue = normalFormData.targetValue(initialState); // The value is already known, nothing to do. + } else { + STORM_LOG_THROW(!normalFormData.observationFailureStates.get(initialState), storm::exceptions::NotSupportedException, + "Trying to compute undefined conditional probability: the condition has probability 0 under all policies."); + // The last case for a terminal initial state is that it is already target and the condition is reachable with non-zero probability. + // In this case, all schedulers induce a conditional probability of 1 (or do not reach the condition, i.e., have undefined value) + initialStateValue = storm::utility::one(); + } + } else if (algString == "restart" || algString == "default") { + initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); + } + return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); +} + +template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, + storm::storage::BitVector const& conditionStates); + +template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, + storm::storage::BitVector const& conditionStates); + +} // namespace storm::modelchecker diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.h b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h new file mode 100644 index 0000000000..12e8c0791e --- /dev/null +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "storm/solver/SolveGoal.h" + +namespace storm { +class Environment; + +namespace storage { +class BitVector; +template +class SparseMatrix; +} // namespace storage + +namespace modelchecker { +class CheckResult; + +namespace utility { +template +class BackwardTransitionCache; +} + +template +std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates); + +} // namespace modelchecker +} // namespace storm diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index a82243a142..8441c324bc 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -3,6 +3,7 @@ #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/InvalidStateException.h" #include "storm/logic/FragmentSpecification.h" +#include "storm/modelchecker/helper/conditional/ConditionalHelper.h" #include "storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h" #include "storm/modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h" #include "storm/modelchecker/helper/ltl/SparseLTLHelper.h" @@ -273,10 +274,13 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - - return storm::modelchecker::helper::SparseMdpPrctlHelper::computeConditionalProbabilities( - env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), - this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + if constexpr (std::is_same_v) { + throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; + } else { + return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), + this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), + leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + } } template diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index 5c54a91e31..bb5060ea09 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -14,6 +14,7 @@ namespace modules { const std::string ModelCheckerSettings::moduleName = "modelchecker"; const std::string ModelCheckerSettings::filterRewZeroOptionName = "filterrewzero"; const std::string ModelCheckerSettings::ltl2daToolOptionName = "ltl2datool"; +const std::string ModelCheckerSettings::conditionalAlgorithmOptionName = "conditional"; ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, filterRewZeroOptionName, false, @@ -27,6 +28,10 @@ ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { "filename", "A script that can be called with a prefix formula and a name for the output automaton.") .build()) .build()); + this->addOption(storm::settings::OptionBuilder(moduleName, conditionalAlgorithmOptionName, false, "The used algorithm for conditional probabilities.") + .setIsAdvanced() + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("alg", "name.").build()) + .build()); } bool ModelCheckerSettings::isFilterRewZeroSet() const { @@ -41,6 +46,12 @@ std::string ModelCheckerSettings::getLtl2daTool() const { return this->getOption(ltl2daToolOptionName).getArgumentByName("filename").getValueAsString(); } +std::string ModelCheckerSettings::getConditionalAlgorithm() const { // TODO + return this->getOption(conditionalAlgorithmOptionName).getHasOptionBeenSet() + ? this->getOption(conditionalAlgorithmOptionName).getArgumentByName("alg").getValueAsString() + : "default"; +} + } // namespace modules } // namespace settings } // namespace storm diff --git a/src/storm/settings/modules/ModelCheckerSettings.h b/src/storm/settings/modules/ModelCheckerSettings.h index 1679289e0c..3ffb7a6eb4 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.h +++ b/src/storm/settings/modules/ModelCheckerSettings.h @@ -35,6 +35,8 @@ class ModelCheckerSettings : public ModuleSettings { */ std::string getLtl2daTool() const; + std::string getConditionalAlgorithm() const; // TODO: do this properly + // The name of the module. static const std::string moduleName; @@ -42,6 +44,7 @@ class ModelCheckerSettings : public ModuleSettings { // Define the string names of the options as constants. static const std::string filterRewZeroOptionName; static const std::string ltl2daToolOptionName; + static const std::string conditionalAlgorithmOptionName; }; } // namespace modules From ba6ff95fcd046935b47dad372315f69ece305fd8 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 18 Nov 2024 10:16:26 +0100 Subject: [PATCH 008/102] Working verimon generator --- .../generator/GenerateMonitorVerifier.cpp | 186 ++++++++++-------- .../generator/GenerateMonitorVerifier.h | 9 +- 2 files changed, 116 insertions(+), 79 deletions(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index 511cbe180e..79b233beac 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -1,8 +1,14 @@ #include "storm-pomdp/generator/GenerateMonitorVerifier.h" +#include +#include #include +#include #include "storm/adapters/RationalNumberAdapter.h" -#include "storm/api/builder.h" +#include "storm/exceptions/InvalidArgumentException.h" +#include "storm/storage/expressions/ExpressionManager.h" +#include "storm/utility/constants.h" +#include "storm/utility/macros.h" namespace storm { namespace generator { @@ -10,9 +16,7 @@ namespace generator { template MonitorVerifier::MonitorVerifier(const models::sparse::Pomdp& product, const std::map, uint32_t>& observationMap) - : product(storm::models::sparse::Pomdp(product)), observationMap(observationMap) { - std::cout << "copying" << std::endl; -} + : product(storm::models::sparse::Pomdp(product)), observationMap(observationMap) {} template const std::map, uint32_t>& MonitorVerifier::getObservationMap() { @@ -26,14 +30,19 @@ const models::sparse::Pomdp& MonitorVerifier::getProduct() template GenerateMonitorVerifier::GenerateMonitorVerifier(models::sparse::Dtmc const& mc, models::sparse::Mdp const& monitor, - Options const& options) - : mc(mc), monitor(monitor), options(options) {} + std::shared_ptr& exprManager, Options const& options) + : mc(mc), monitor(monitor), risk(), exprManager(exprManager), options(options) { + monvar = exprManager->declareFreshIntegerVariable(false, "_mon"); + mcvar = exprManager->declareFreshIntegerVariable(false, "_mc"); +} template std::shared_ptr> GenerateMonitorVerifier::createProduct() { typedef storm::storage::sparse::state_type state_type; typedef std::pair product_state_type; + STORM_LOG_THROW(monitor.hasChoiceLabeling(), storm::exceptions::InvalidArgumentException, "The monitor should contain choice labeling"); + const std::set& actions = monitor.getChoiceLabeling().getLabels(); uint32_t nextObservation = 0; @@ -46,7 +55,7 @@ std::shared_ptr> GenerateMonitorVerifier:: } actionMap["end"]; - storm::storage::SparseMatrixBuilder builder(0, 0, 0, false, true, 0); + storm::storage::SparseMatrixBuilder builder(0, 0, 0, false, true); std::size_t currentRow = 0; state_type nextStateId = 0; @@ -68,7 +77,7 @@ std::shared_ptr> GenerateMonitorVerifier:: std::deque todo; for (state_type mc_s_0 : mc.getInitialStates()) { for (state_type mon_s_0 : monitor.getInitialStates()) { - product_state_type prod_s(mon_s_0, mc_s_0); + product_state_type prod_s(mc_s_0, mon_s_0); state_type index = nextStateId++; prodToIndexMap[prod_s] = index; prodInitial.push_back(index); @@ -106,15 +115,17 @@ std::shared_ptr> GenerateMonitorVerifier:: } } else { std::size_t numMonRows = monitor.getTransitionMatrix().getRowGroupSize(mon_from); + std::size_t monGroupStart = monitor.getTransitionMatrix().getRowGroupIndices()[mon_from]; std::set actionsNotTaken(actions); for (std::size_t i = 0; i < numMonRows; i++) { // Remove labels of monitor choice from the labels we still have to take - STORM_LOG_ASSERT(monitor.getChoiceLabeling().getLabelsOfChoice(mon_from + i).size() == 1, "Monitor choice has not exactly one choice label"); - const auto action = *monitor.getChoiceLabeling().getLabelsOfChoice(mon_from + i).begin(); + STORM_LOG_ASSERT(monitor.getChoiceLabeling().getLabelsOfChoice(monGroupStart + i).size() == 1, + "Monitor choice has not exactly one choice label"); + const auto action = *monitor.getChoiceLabeling().getLabelsOfChoice(monGroupStart + i).begin(); actionsNotTaken.erase(action); const auto& monitorRow = monitor.getTransitionMatrix().getRow(mon_from, i); - STORM_LOG_ASSERT(monitorRow.getNumberOfEntries() == 1, "Monitor is not fully deterministic in"); + STORM_LOG_ASSERT(monitorRow.getNumberOfEntries() == 1, "Monitor is not fully deterministic"); const auto& monitorEntry = monitorRow.begin(); const auto& mcRow = mc.getTransitionMatrix().getRow(mc_from); @@ -177,10 +188,15 @@ std::shared_ptr> GenerateMonitorVerifier:: } if (monitor.getStateLabeling().getStateHasLabel(options.acceptingLabel, mon_from)) { - if (mc.getStateLabeling().getStateHasLabel(options.goodLabel, mc_from)) { - builder.addNextValue(currentRow, goalIndex, utility::one()); + if (options.useRisk) { + builder.addNextValue(currentRow, goalIndex, risk[mc_from]); + builder.addNextValue(currentRow, stopIndex, utility::one() - risk[mc_from]); } else { - builder.addNextValue(currentRow, stopIndex, utility::one()); + if (mc.getStateLabeling().getStateHasLabel(options.goodLabel, mc_from)) { + builder.addNextValue(currentRow, goalIndex, utility::one()); + } else { + builder.addNextValue(currentRow, stopIndex, utility::one()); + } } actionMap["end"].push_back(currentRow); currentRow++; @@ -198,6 +214,9 @@ std::shared_ptr> GenerateMonitorVerifier:: stateLabeling.addLabel("stop", storm::storage::BitVector(numberOfStates)); stateLabeling.addLabelToState("stop", stopIndex); + storm::storage::sparse::ModelComponents components(builder.build(), std::move(stateLabeling)); + components.observabilityClasses = std::move(observations); + // Add choice labeling const size_t numberOfRows = currentRow; storm::models::sparse::ChoiceLabeling choiceLabeling(numberOfRows); @@ -205,88 +224,99 @@ std::shared_ptr> GenerateMonitorVerifier:: choiceLabeling.addLabel(label, storm::storage::BitVector(numberOfRows, vec.begin(), vec.end())); } - // Add state valuations - storm::storage::sparse::StateValuationsBuilder svBuilder; - std::set variables; - for (auto i = 0; i < mc.getNumberOfStates(); i++) { - const auto& valAssignment = mc.getStateValuations().at(i); - for (auto val = valAssignment.begin(); val != valAssignment.end(); ++val) { - if (val.isVariableAssignment() && !variables.contains(val.getVariable())) { - variables.emplace(val.getVariable()); - svBuilder.addVariable(val.getVariable()); - } - } - } - - for (auto i = 0; i < mc.getNumberOfStates(); i++) { - for (auto j = 0; j < monitor.getNumberOfStates(); j++) { - product_state_type s(i, j); - if (!prodToIndexMap.contains(s)) - continue; - - std::vector booleanValues; - std::vector integerValues; - std::vector rationalValues; + components.choiceLabeling = std::move(choiceLabeling); + if (mc.hasStateValuations()) { + // Add state valuations + storm::storage::sparse::StateValuationsBuilder svBuilder; + svBuilder.addVariable(monvar); + svBuilder.addVariable(mcvar); + std::set variables; + for (auto i = 0; i < mc.getNumberOfStates(); i++) { const auto& valAssignment = mc.getStateValuations().at(i); + for (auto val = valAssignment.begin(); val != valAssignment.end(); ++val) { + if (val.isVariableAssignment() && !variables.contains(val.getVariable())) { + variables.emplace(val.getVariable()); + svBuilder.addVariable(val.getVariable()); + } + } + } - for (auto& var : variables) { - for (auto val = valAssignment.begin(); val != valAssignment.end(); ++val) { - if (var == val.getVariable()) { - if (val.isBoolean()) { - booleanValues.push_back(val.getBooleanValue()); - } else if (val.isInteger()) { - integerValues.push_back(val.getIntegerValue()); - } else if (val.isRational()) { - rationalValues.push_back(val.getRationalValue()); + for (auto i = 0; i < mc.getNumberOfStates(); i++) { + for (auto j = 0; j < monitor.getNumberOfStates(); j++) { + product_state_type s(i, j); + if (!prodToIndexMap.contains(s)) + continue; + + std::vector booleanValues; + std::vector integerValues; + std::vector rationalValues; + + integerValues.push_back(j); // Set monvar + integerValues.push_back(i); // Set mcvar + + const auto& valAssignment = mc.getStateValuations().at(i); + + for (auto& var : variables) { + for (auto val = valAssignment.begin(); val != valAssignment.end(); ++val) { + if (var == val.getVariable()) { + if (val.isBoolean()) { + booleanValues.push_back(val.getBooleanValue()); + } else if (val.isInteger()) { + integerValues.push_back(val.getIntegerValue()); + } else if (val.isRational()) { + rationalValues.push_back(val.getRationalValue()); + } + break; } - break; } } + svBuilder.addState(prodToIndexMap[std::make_pair(i, j)], std::move(booleanValues), std::move(integerValues), std::move(rationalValues)); } - svBuilder.addState(prodToIndexMap[std::make_pair(i, j)], std::move(booleanValues), std::move(integerValues), std::move(rationalValues)); } - } - std::vector goalBooleanValues; - std::vector goalIntegerValues; - std::vector goalRationalValues; - for (auto& var : variables) { - if (var.hasBooleanType()) { - goalBooleanValues.push_back(false); - } else if (var.hasIntegerType()) { - goalIntegerValues.push_back(-1); - } else if (var.hasRationalType()) { - goalRationalValues.emplace_back(-1); + std::vector goalBooleanValues; + std::vector goalIntegerValues(2, -1); + std::vector goalRationalValues; + for (auto& var : variables) { + if (var.hasBooleanType()) { + goalBooleanValues.push_back(false); + } else if (var.hasIntegerType()) { + goalIntegerValues.push_back(-1); + } else if (var.hasRationalType()) { + goalRationalValues.emplace_back(-1); + } } - } - svBuilder.addState(goalIndex, std::move(goalBooleanValues), std::move(goalIntegerValues), std::move(goalRationalValues)); - - std::vector stopBooleanValues; - std::vector stopIntegerValues; - std::vector stopRationalValues; - for (auto& var : variables) { - if (var.hasBooleanType()) { - stopBooleanValues.push_back(false); - } else if (var.hasIntegerType()) { - stopIntegerValues.push_back(-1); - } else if (var.hasRationalType()) { - stopRationalValues.emplace_back(-1); + svBuilder.addState(goalIndex, std::move(goalBooleanValues), std::move(goalIntegerValues), std::move(goalRationalValues)); + + std::vector stopBooleanValues; + std::vector stopIntegerValues(2, -1); + std::vector stopRationalValues; + for (auto& var : variables) { + if (var.hasBooleanType()) { + stopBooleanValues.push_back(false); + } else if (var.hasIntegerType()) { + stopIntegerValues.push_back(-1); + } else if (var.hasRationalType()) { + stopRationalValues.emplace_back(-1); + } } + svBuilder.addState(stopIndex, std::move(stopBooleanValues), std::move(stopIntegerValues), std::move(stopRationalValues)); + + components.stateValuations = svBuilder.build(); } - svBuilder.addState(stopIndex, std::move(stopBooleanValues), std::move(stopIntegerValues), std::move(stopRationalValues)); - // Build model - storm::storage::sparse::ModelComponents components(builder.build(), std::move(stateLabeling)); - components.observabilityClasses = std::move(observations); - components.choiceLabeling = std::move(choiceLabeling); - components.stateValuations = svBuilder.build(); + // Store model storm::models::sparse::Pomdp product(std::move(components)); auto mv = std::make_shared>(std::move(product), std::move(observationMap)); - std::cout << mv->getProduct().getNrObservations() << std::endl; return mv; } +template +void GenerateMonitorVerifier::setRisk(std::vector const& risk) { + this->risk = risk; +} + template class MonitorVerifier; template class MonitorVerifier; template class GenerateMonitorVerifier; diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.h b/src/storm-pomdp/generator/GenerateMonitorVerifier.h index 62bb1e74dc..a632293530 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.h +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.h @@ -26,13 +26,20 @@ class GenerateMonitorVerifier { std::string acceptingLabel = "accepting"; std::string stepPrefix = "step"; std::string horizonLabel = "horizon"; + bool useRisk = false; }; - GenerateMonitorVerifier(storm::models::sparse::Dtmc const& mc, storm::models::sparse::Mdp const& monitor, Options const& options); + GenerateMonitorVerifier(storm::models::sparse::Dtmc const& mc, storm::models::sparse::Mdp const& monitor, + std::shared_ptr& exprManager, Options const& options); std::shared_ptr> createProduct(); + void setRisk(std::vector const& risk); private: const storm::models::sparse::Dtmc& mc; const storm::models::sparse::Mdp& monitor; + std::shared_ptr& exprManager; + std::vector risk; + storm::expressions::Variable monvar; + storm::expressions::Variable mcvar; Options options; }; From 8dd82527ff7ea917094b0b5503a3078c7b7ffb00 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 20 Nov 2024 11:45:15 +0100 Subject: [PATCH 009/102] Time measurements for conditional probability computation --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 9d4676a8e2..4c345ad360 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -8,6 +8,7 @@ #include "storm/storage/MaximalEndComponentDecomposition.h" #include "storm/storage/SparseMatrix.h" #include "storm/transformer/EndComponentEliminator.h" +#include "storm/utility/Stopwatch.h" #include "storm/utility/graph.h" #include "storm/utility/macros.h" @@ -243,9 +244,12 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // @see doi.org/10.1007/978-3-642-54862-8_43 STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, "Only one initial state is supported for conditional probabilities"); + storm::utility::Stopwatch sw(true); auto normalFormData = internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, targetStates, conditionStates); + STORM_PRINT_AND_LOG("Time for obtaining the normal form:" << sw << ".\n"); - // Then, we solve the induced problem using the selected algorithm. + sw.restart(); + // Then, we solve the induced problem using the selected algorithm[p auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); auto const algString = storm::settings::getModule().getConditionalAlgorithm(); @@ -264,6 +268,7 @@ std::unique_ptr computeConditionalProbabilities(Environment const& } else { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); } + STORM_PRINT_AND_LOG("Time for analyzing the normal form:" << sw << ".\n"); return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); } From d98f30297c506166b4a1c42f43b27eacaec4fd79 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 21 Nov 2024 10:03:52 +0100 Subject: [PATCH 010/102] Optimize verimon by removing superfluos actions --- .../generator/GenerateMonitorVerifier.cpp | 150 +++++++++++++----- 1 file changed, 112 insertions(+), 38 deletions(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index 79b233beac..ca9422922c 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -1,11 +1,20 @@ #include "storm-pomdp/generator/GenerateMonitorVerifier.h" +#include +#include #include +#include #include +#include +#include +#include #include #include #include "storm/adapters/RationalNumberAdapter.h" +#include "storm/exceptions/AbortException.h" #include "storm/exceptions/InvalidArgumentException.h" +#include "storm/storage/BitVector.h" +#include "storm/storage/SparseMatrix.h" #include "storm/storage/expressions/ExpressionManager.h" #include "storm/utility/constants.h" #include "storm/utility/macros.h" @@ -45,15 +54,20 @@ std::shared_ptr> GenerateMonitorVerifier:: const std::set& actions = monitor.getChoiceLabeling().getLabels(); + // Build choice label map of monitor choices + std::vector monitorChoiceLabels; + for (auto i = 0; i < monitor.getTransitionMatrix().getRowCount(); i++) { + auto const& monitorLabels = monitor.getChoiceLabeling().getLabelsOfChoice(i); + STORM_LOG_THROW(monitorLabels.size() == 1, storm::exceptions::InvalidArgumentException, "Monitor choice has not exactly one choice label"); + monitorChoiceLabels.push_back(*monitorLabels.begin()); + } + uint32_t nextObservation = 0; std::map, uint32_t> observationMap; std::vector observations; - std::map> actionMap; - for (auto const& action : actions) { - actionMap[action]; - } - actionMap["end"]; + std::map, storage::BitVector> rowActionObservationMap; + std::vector> observationUsedActions; storm::storage::SparseMatrixBuilder builder(0, 0, 0, false, true); std::size_t currentRow = 0; @@ -61,13 +75,17 @@ std::shared_ptr> GenerateMonitorVerifier:: state_type goalIndex = nextStateId++; builder.newRowGroup(currentRow); - actionMap["end"].push_back(currentRow); + rowActionObservationMap[std::make_pair("end", nextObservation)].grow(currentRow + 1); + rowActionObservationMap[std::make_pair("end", nextObservation)].set(currentRow); + observationUsedActions.push_back({"end"}); builder.addDiagonalEntry(currentRow++, utility::one()); observations.push_back(nextObservation++); state_type stopIndex = nextStateId++; builder.newRowGroup(currentRow); - actionMap["end"].push_back(currentRow); + rowActionObservationMap[std::make_pair("end", nextObservation)].grow(currentRow + 1); + rowActionObservationMap[std::make_pair("end", nextObservation)].set(currentRow); + observationUsedActions.push_back({"end"}); builder.addDiagonalEntry(currentRow++, utility::one()); observations.push_back(nextObservation++); @@ -100,28 +118,30 @@ std::shared_ptr> GenerateMonitorVerifier:: std::pair obsPair(step, accepting); if (!observationMap.contains(obsPair)) { observationMap[obsPair] = nextObservation++; + observationUsedActions.push_back(std::set()); } - observations.push_back(observationMap.at(obsPair)); + u_int32_t currentObservation = observationMap.at(obsPair); + observations.push_back(currentObservation); // Set transitions for from and add new states to todo builder.newRowGroup(currentRow); if (monitor.getStateLabeling().getLabelsOfState(mon_from).contains(options.horizonLabel)) { - for (const auto& action : actions) { - for (state_type initState : prodInitial) { - builder.addNextValue(currentRow, initState, storm::utility::one() / prodInitial.size()); - } - actionMap[action].push_back(currentRow); - currentRow++; + const auto& action = *actions.begin(); + for (state_type initState : prodInitial) { + builder.addNextValue(currentRow, initState, storm::utility::one() / prodInitial.size()); } + rowActionObservationMap[std::make_pair(action, currentObservation)].grow(currentRow + 1); + rowActionObservationMap[std::make_pair(action, currentObservation)].set(currentRow); + observationUsedActions[currentObservation].emplace(action); + currentRow++; } else { std::size_t numMonRows = monitor.getTransitionMatrix().getRowGroupSize(mon_from); std::size_t monGroupStart = monitor.getTransitionMatrix().getRowGroupIndices()[mon_from]; std::set actionsNotTaken(actions); for (std::size_t i = 0; i < numMonRows; i++) { // Remove labels of monitor choice from the labels we still have to take - STORM_LOG_ASSERT(monitor.getChoiceLabeling().getLabelsOfChoice(monGroupStart + i).size() == 1, - "Monitor choice has not exactly one choice label"); - const auto action = *monitor.getChoiceLabeling().getLabelsOfChoice(monGroupStart + i).begin(); + + const auto action = monitorChoiceLabels[monGroupStart + i]; actionsNotTaken.erase(action); const auto& monitorRow = monitor.getTransitionMatrix().getRow(mon_from, i); @@ -152,29 +172,36 @@ std::shared_ptr> GenerateMonitorVerifier:: } // Add transitions to the successors, if the successor has not yet been added, add it to the todo list - for (const auto& mcEntry : mcRow) { - if (mc.getStateLabeling().getStateHasLabel(action, mcEntry.getColumn())) { - const product_state_type to_pair(mcEntry.getColumn(), monitorEntry->getColumn()); - state_type indexTo; - if (auto it = prodToIndexMap.find(to_pair); it != prodToIndexMap.end()) { - indexTo = it->second; - } else { - indexTo = nextStateId++; - todo.push_back(to_pair); - prodToIndexMap[to_pair] = indexTo; + if (totalProbability > storm::utility::zero()) { + for (const auto& mcEntry : mcRow) { + if (mc.getStateLabeling().getStateHasLabel(action, mcEntry.getColumn())) { + const product_state_type to_pair(mcEntry.getColumn(), monitorEntry->getColumn()); + state_type indexTo; + if (auto it = prodToIndexMap.find(to_pair); it != prodToIndexMap.end()) { + indexTo = it->second; + } else { + indexTo = nextStateId++; + todo.push_back(to_pair); + prodToIndexMap[to_pair] = indexTo; + } + if (newRow.contains(indexTo)) + newRow[indexTo] = newRow[indexTo] + mcEntry.getValue(); + else + newRow[indexTo] = mcEntry.getValue(); } - if (newRow.contains(indexTo)) - newRow[indexTo] = newRow[indexTo] + mcEntry.getValue(); - else - newRow[indexTo] = mcEntry.getValue(); } + + // Set action to used for this observation + observationUsedActions[currentObservation].emplace(action); } // Insert new entries for (const auto& entry : newRow) { builder.addNextValue(currentRow, entry.first, entry.second); } - actionMap[action].push_back(currentRow); + auto& rowBitVec = rowActionObservationMap[std::make_pair(action, currentObservation)]; + rowBitVec.grow(currentRow + 1); + rowBitVec.set(currentRow); currentRow++; } @@ -182,7 +209,9 @@ std::shared_ptr> GenerateMonitorVerifier:: for (state_type initState : prodInitial) { builder.addNextValue(currentRow, initState, storm::utility::one() / prodInitial.size()); } - actionMap[action].push_back(currentRow); + auto& rowBitVec = rowActionObservationMap[std::make_pair(action, currentObservation)]; + rowBitVec.grow(currentRow + 1); + rowBitVec.set(currentRow); currentRow++; } } @@ -198,11 +227,44 @@ std::shared_ptr> GenerateMonitorVerifier:: builder.addNextValue(currentRow, stopIndex, utility::one()); } } - actionMap["end"].push_back(currentRow); + observationUsedActions[currentObservation].emplace("end"); + auto& rowBitVec = rowActionObservationMap[std::make_pair("end", currentObservation)]; + rowBitVec.grow(currentRow + 1); + rowBitVec.set(currentRow); currentRow++; } } + size_t numberOfRows = currentRow; + + // Make all observation action bitvectors of size numberOfRows + for (auto& [labelObsPair, vec] : rowActionObservationMap) { + vec.resize(numberOfRows); + } + + // Calculate which rows belong to action which don't all return for an observation and only keep these + storm::storage::SparseMatrix transMatrix = builder.build(); + storm::storage::BitVector rowsToKeep(transMatrix.getRowCount()); + u_int32_t currentObservation = 0; + for (auto const& actionsInObs : observationUsedActions) { + for (auto const& action : actionsInObs) { + // std::cout << "Keeping action obs (" << action << ", " << currentObservation << ")" << std::endl; + rowsToKeep |= rowActionObservationMap[std::make_pair(action, currentObservation)]; + } + currentObservation++; + } + // std::cout << "Kept " << rowsToKeep.getNumberOfSetBits() << " out of " << numberOfRows << " rows." << std::endl; + numberOfRows = rowsToKeep.getNumberOfSetBits(); + storm::storage::SparseMatrix reducedTransitionMatrix = transMatrix.restrictRows(rowsToKeep); + // rowsToKeep.complement(); + // storm::storage::SparseMatrix inverseReducedTransitionMatrix = transMatrix.restrictRows(rowsToKeep, true); + // for (auto row = 0; row < inverseReducedTransitionMatrix.getRowCount(); ++row) { + // STORM_LOG_THROW(inverseReducedTransitionMatrix.getRow(row).getNumberOfEntries() == prodInitial.size(), storm::exceptions::AbortException, + // "Only dirac rows can be thrown away but " + std::to_string(row) + " is thrown away"); + // } + // rowsToKeep.complement(); + // auto reducedTransitionMatrix = builder.build(); + // Create state labeling const state_type numberOfStates = nextStateId; storm::models::sparse::StateLabeling stateLabeling(numberOfStates); @@ -214,14 +276,26 @@ std::shared_ptr> GenerateMonitorVerifier:: stateLabeling.addLabel("stop", storm::storage::BitVector(numberOfStates)); stateLabeling.addLabelToState("stop", stopIndex); - storm::storage::sparse::ModelComponents components(builder.build(), std::move(stateLabeling)); + storm::storage::sparse::ModelComponents components(reducedTransitionMatrix, std::move(stateLabeling)); components.observabilityClasses = std::move(observations); // Add choice labeling - const size_t numberOfRows = currentRow; + const std::vector rowMapping = rowsToKeep.getNumberOfSetBitsBeforeIndices(); // Vector which maps old row id to new row id storm::models::sparse::ChoiceLabeling choiceLabeling(numberOfRows); - for (const auto& [label, vec] : actionMap) { - choiceLabeling.addLabel(label, storm::storage::BitVector(numberOfRows, vec.begin(), vec.end())); + for (const auto& [labelObsPair, bitvec] : rowActionObservationMap) { + // Rebuild bitvec with restricted rows + storm::storage::BitVector newBitVec(numberOfRows); + for (const auto& setbit : bitvec) { + if (rowsToKeep[setbit]) + newBitVec.set(rowMapping[setbit]); + } + // auto newBitVec = bitvec; + + if (choiceLabeling.containsLabel(labelObsPair.first)) { + choiceLabeling.setChoices(labelObsPair.first, newBitVec | choiceLabeling.getChoices(labelObsPair.first)); + } else { + choiceLabeling.addLabel(labelObsPair.first, newBitVec); + } } components.choiceLabeling = std::move(choiceLabeling); From 87654d4f03e906270c41acfe7abb32eea1098aab Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 27 Nov 2024 14:25:02 +0100 Subject: [PATCH 011/102] First version of binary approach --- .../helper/conditional/ConditionalHelper.cpp | 381 +++++++++++++++--- 1 file changed, 326 insertions(+), 55 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 4c345ad360..7aedab0352 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -1,6 +1,10 @@ +#include +#include + #include "storm/modelchecker/helper/conditional/ConditionalHelper.h" #include "storm/adapters/RationalNumberAdapter.h" +#include "storm/environment/solver/MinMaxSolverEnvironment.h" #include "storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/solver/SolveGoal.h" @@ -22,32 +26,72 @@ namespace storm::modelchecker { namespace internal { -template -SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix&& matrix, std::vector&& rowValues, - storm::OptionalRef const& rowsWithSum1, storm::solver::OptimizationDirection const dir, - uint64_t const initialState) { - if (rowsWithSum1.has_value()) { - storm::storage::BitVector const allRowGroups(matrix.getRowGroupCount(), true); - storm::storage::BitVector const noRowGroups(matrix.getRowGroupCount(), false); - storm::storage::MaximalEndComponentDecomposition mecs(matrix, matrix.transpose(true), allRowGroups, *rowsWithSum1); - if (!mecs.empty()) { - auto ecElimResult = storm::transformer::EndComponentEliminator::transform(matrix, mecs, allRowGroups, noRowGroups); - std::vector newRowValues; - newRowValues.reserve(ecElimResult.newToOldRowMapping.size()); - for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { - newRowValues.push_back(rowValues[oldRowIndex]); - } - return solveMinMaxEquationSystem(env, std::move(ecElimResult.matrix), std::move(newRowValues), storm::NullRef, dir, - ecElimResult.oldToNewStateMapping[initialState]); +template +void eliminateEndComponents(storm::storage::BitVector possibleEcStates, bool addRowAtRepresentativeState, std::optional representativeRowEntry, + storm::storage::SparseMatrix& matrix, uint64_t& initialState, storm::storage::BitVector& rowsWithSum1, + std::vector& rowValues1, storm::OptionalRef> rowValues2 = {}) { + storm::storage::MaximalEndComponentDecomposition ecs(matrix, matrix.transpose(true), possibleEcStates, rowsWithSum1); + if (ecs.empty()) { + return; // nothing to do + } + + storm::storage::BitVector allRowGroups(matrix.getRowGroupCount(), true); + auto ecElimResult = storm::transformer::EndComponentEliminator::transform( + matrix, ecs, allRowGroups, addRowAtRepresentativeState ? allRowGroups : ~allRowGroups, representativeRowEntry.has_value()); + + // Update matrix + matrix = std::move(ecElimResult.matrix); + if (addRowAtRepresentativeState && representativeRowEntry) { + auto const columnIndex = ecElimResult.oldToNewStateMapping[*representativeRowEntry]; + for (auto representativeRowIndex : ecElimResult.sinkRows) { + auto row = matrix.getRow(representativeRowIndex); + STORM_LOG_ASSERT(row.getNumberOfEntries() == 1, "unexpected number of entries in representative row."); + auto& entry = *row.begin(); + entry.setColumn(columnIndex); + } + } + + // update vectors + auto updateRowValue = [&ecElimResult](std::vector& rowValues) { + std::vector newRowValues; + newRowValues.reserve(ecElimResult.newToOldRowMapping.size()); + for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { + newRowValues.push_back(rowValues[oldRowIndex]); } + rowValues = std::move(newRowValues); + STORM_LOG_ASSERT( + std::all_of(ecElimResult.sinkRows.begin(), ecElimResult.sinkRows.end(), [&rowValues](auto i) { return storm::utility::isZero(rowValues[i]); }), + "Sink rows are expected to have zero value"); + }; + updateRowValue(rowValues1); + if (rowValues2) { + updateRowValue(*rowValues2); } + // update initial state + initialState = ecElimResult.oldToNewStateMapping[initialState]; + + // update bitvector + storm::storage::BitVector newRowsWithSum1(ecElimResult.newToOldRowMapping.size(), true); + uint64_t newRowIndex = 0; + for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { + if ((addRowAtRepresentativeState && !representativeRowEntry.has_value() && ecElimResult.sinkRows.get(newRowIndex)) || !rowsWithSum1.get(oldRowIndex)) { + newRowsWithSum1.set(newRowIndex, false); + } + ++newRowIndex; + } + rowsWithSum1 = std::move(newRowsWithSum1); +} + +template +SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, + std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, + storm::solver::OptimizationDirection const dir, uint64_t const initialState) { // Initialize the solution vector. std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); // Set up the solver. - auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create( - env, std::forward>(matrix)); + auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(env, matrix); solver->setOptimizationDirection(dir); solver->setRequirementsChecked(); solver->setHasUniqueSolution(true); @@ -95,12 +139,13 @@ void computeReachabilityProbabilities(Environment const& env, std::map struct NormalFormData { - storm::storage::BitVector const - definedStates; // Those states where the property is defined, i.e., the condition states can be reached with positive probability - storm::storage::BitVector const terminalStates; // Those states where we already know the probability to reach the condition and the target value - storm::storage::BitVector const conditionStates; // Those states where the condition holds almost surely (under all schedulers) - storm::storage::BitVector const observationFailureStates; // Those states where the condition is not reachable (under all schedulers) - std::map const nonZeroTargetStateValues; // The known non-zero target values. (default is zero) + storm::storage::BitVector const maybeStates; // Those states that can be reached from initial without reaching a terminal state + storm::storage::BitVector const terminalStates; // Those states where we already know the probability to reach the condition and the target value + storm::storage::BitVector const conditionStates; // Those states where the condition holds almost surely (under all schedulers) + storm::storage::BitVector const universalObservationFailureStates; // Those states where the condition is not reachable (under all schedulers) + storm::storage::BitVector const existentialObservationFailureStates; // Those states s where a scheduler exists that (i) does not reach the condition from + // s and (ii) acts optimal in all terminal states + std::map const nonZeroTargetStateValues; // The known non-zero target values. (default is zero) // There are three cases of terminal states: // 1. conditionStates: The condition holds, so the target value is the optimal probability to reach target from there // 2. targetStates: The target is reached, so the target value is the optimal probability to reach a condition from there. @@ -127,41 +172,50 @@ struct NormalFormData { template NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, - storm::storage::BitVector const& conditionStates) { + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& relevantStates, + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { storm::storage::BitVector const allStates(transitionMatrix.getRowGroupCount(), true); auto extendedConditionStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); - auto observationFailureStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); + auto universalObservationFailureStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); std::map nonZeroTargetStateValues; auto const extendedTargetStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, targetStates); computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); - auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | observationFailureStates); + auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates); computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); - auto terminalStates = extendedConditionStates | extendedTargetStates | observationFailureStates; + auto terminalStates = extendedConditionStates | extendedTargetStates | universalObservationFailureStates; + + // get states where the optimal policy reaches the condition with positive probability + auto terminalStatesThatReachCondition = extendedConditionStates; + for (auto state : targetAndNotCondFailStates) { + if (nonZeroTargetStateValues.contains(state)) { + terminalStatesThatReachCondition.set(state, true); + } + } if (storm::solver::minimize(dir)) { - // There can be targetAndNotCondFailStates from which only the *minimal* probability to reach a condition is zero. + // There can be target states from which (only) the *minimal* probability to reach a condition is zero. // For those states, the optimal policy is to enforce observation failure. // States that can only reach (target states with almost sure observation failure) or observation failure will be treated as terminal states with // targetValue zero and failProbability one. - - // We first determine states where the optimal policy reaches the condition with positive probability - auto terminalStatesThatReachCondition = extendedConditionStates; - for (auto state : targetAndNotCondFailStates) { - if (nonZeroTargetStateValues.contains(state)) { - terminalStatesThatReachCondition.set(state, true); - } - } - // Then, we determine the non-terminal states that cannot reach such states. terminalStates |= storm::utility::graph::performProb0A(backwardTransitions, ~terminalStates, terminalStatesThatReachCondition); } - return NormalFormData{.terminalStates = std::move(terminalStates), + auto nonTerminalStates = ~terminalStates; + + auto existentialObservationFailureStates = storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), + backwardTransitions, nonTerminalStates, terminalStatesThatReachCondition); + + // Restrict non-terminal states to those that are still relevant + nonTerminalStates &= storm::utility::graph::getReachableStates(transitionMatrix, relevantStates, nonTerminalStates, terminalStates); + + return NormalFormData{.maybeStates = std::move(nonTerminalStates), + .terminalStates = std::move(terminalStates), .conditionStates = std::move(extendedConditionStates), - .observationFailureStates = std::move(observationFailureStates), + .universalObservationFailureStates = std::move(universalObservationFailureStates), + .existentialObservationFailureStates = std::move(existentialObservationFailureStates), .nonZeroTargetStateValues = std::move(nonZeroTargetStateValues)}; } @@ -172,7 +226,7 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver template SolutionType computeViaRestartMethod(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { - auto const maybeStates = ~normalForm.terminalStates; + auto const& maybeStates = normalForm.maybeStates; auto const stateToMatrixIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); auto const numMaybeStates = maybeStates.getNumberOfSetBits(); auto const numMaybeChoices = transitionMatrix.getNumRowsInRowGroups(maybeStates); @@ -230,7 +284,212 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init } } - return solveMinMaxEquationSystem(env, matrixBuilder.build(), std::move(rowValues), rowsWithSum1, dir, stateToMatrixIndexMap[initialState]); + auto matrix = matrixBuilder.build(); + auto initStateInMatrix = stateToMatrixIndexMap[initialState]; + + // Eliminate end components in two phases + // First, we catch all end components that do not contain the initial state. It is possible to stay in those ECs forever + // without reaching the condition. This is reflected by a backloop to the initial state. + storm::storage::BitVector selectedStatesInMatrix(numMaybeChoices, true); + selectedStatesInMatrix.set(initStateInMatrix, false); + eliminateEndComponents(selectedStatesInMatrix, true, initStateInMatrix, matrix, initStateInMatrix, rowsWithSum1, rowValues); + // Second, eliminate the remaining ECs. These must involve the initial state and might have been introduced in the previous step. + // A policy selecting such an EC must reach the condition with probability zero and is thus invalid. + selectedStatesInMatrix.set(initStateInMatrix, true); + eliminateEndComponents(selectedStatesInMatrix, false, std::nullopt, matrix, initStateInMatrix, rowsWithSum1, rowValues); + + STORM_PRINT_AND_LOG("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " + << matrix.getEntryCount() << " transitions.\n"); + // Finally, solve the equation system + return solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); +} + +template +class WeightedDiffComputer { + public: + WeightedDiffComputer(uint64_t const initialState, storm::storage::SparseMatrix const& transitionMatrix, + NormalFormData const& normalForm) { + // Determine rowgroups (states) and rows (choices) of the submatrix + auto subMatrixRowGroups = normalForm.maybeStates; + // Identify and eliminate the initial component to enforce that it is eventually exited + // The initial component is the largest subset of maybestates C such that + // (i) the initial state is contained in C + // (ii) each state in C can be reached from the initial state while only playing actions that stay inside C or observation failure and + // (iii) for each state in C except the initial state there is a policy that almost surely reaches an observation failure + // An optimal scheduler can intuitively pick the best exiting action of C and enforce that all paths that satisfy the condition exit C through that + // action. By eliminating the initial component, we ensure that only policies that actually exit C are considered. The remaining policies have + // probability zero of satisfying the condition. + storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); + subMatrixRowGroups.set(initialState, false); // temporarily unset initial state + std::vector dfsStack = {initialState}; + while (!dfsStack.empty()) { + auto const state = dfsStack.back(); + dfsStack.pop_back(); + for (auto rowIndex : transitionMatrix.getRowGroupIndices(state)) { + auto const row = transitionMatrix.getRow(rowIndex); + if (std::all_of(row.begin(), row.end(), + [&normalForm](auto const& entry) { return normalForm.existentialObservationFailureStates.get(entry.getColumn()); })) { + for (auto const& entry : row) { + auto const& successor = entry.getColumn(); + if (subMatrixRowGroups.get(successor)) { + subMatrixRowGroups.set(successor, false); + dfsStack.push_back(successor); + } + } + } else { + initialComponentExitRows.set(rowIndex, true); + } + } + } + auto const numSubmatrixRows = transitionMatrix.getNumRowsInRowGroups(subMatrixRowGroups) + initialComponentExitRows.getNumberOfSetBits(); + subMatrixRowGroups.set(initialState, true); // set initial state again, as single representative state for the initial component + auto const numSubmatrixRowGroups = subMatrixRowGroups.getNumberOfSetBits(); + + // state index mapping and initial state + auto stateToMatrixIndexMap = subMatrixRowGroups.getNumberOfSetBitsBeforeIndices(); + initialStateInSubmatrix = stateToMatrixIndexMap[initialState]; + auto const eliminatedInitialComponentStates = normalForm.maybeStates & ~subMatrixRowGroups; + for (auto state : eliminatedInitialComponentStates) { + stateToMatrixIndexMap[state] = initialStateInSubmatrix; // map all eliminated states to the initial state + } + + // build matrix, rows that sum up to 1, target values, condition values + storm::storage::SparseMatrixBuilder matrixBuilder(numSubmatrixRows, numSubmatrixRowGroups, 0, true, true, numSubmatrixRowGroups); + rowsWithSum1 = storm::storage::BitVector(numSubmatrixRows, true); + targetRowValues.reserve(numSubmatrixRows); + conditionRowValues.reserve(numSubmatrixRows); + uint64_t currentRow = 0; + for (auto state : subMatrixRowGroups) { + matrixBuilder.newRowGroup(currentRow); + + // Put the row processing into a lambda for avoiding code duplications + auto processRow = [&](uint64_t origRowIndex) { + // Find out the target and condition probabilities for this row + ValueType targetProbability = storm::utility::zero(); + ValueType conditionProbability = storm::utility::zero(); + bool rowSumIsLess1 = false; + for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { + if (normalForm.terminalStates.get(entry.getColumn())) { + STORM_LOG_ASSERT(!storm::utility::isZero(entry.getValue()), "Transition probability must be non-zero"); + rowSumIsLess1 = true; + ValueType const scaledTargetValue = normalForm.targetValue(entry.getColumn()) * entry.getValue(); + targetProbability += scaledTargetValue; + if (normalForm.conditionStates.get(entry.getColumn())) { + conditionProbability += entry.getValue(); // conditionValue of successor is 1 + } else { + conditionProbability += scaledTargetValue; // for terminal, non-condition states, the condition value equals the target value + } + } else { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[entry.getColumn()], entry.getValue()); + } + } + if (rowSumIsLess1) { + rowsWithSum1.set(currentRow, false); + } + targetRowValues.push_back(targetProbability); + conditionRowValues.push_back(conditionProbability); + ++currentRow; + }; + // invoke the lambda + if (state == initialState) { + for (auto origRowIndex : initialComponentExitRows) { + processRow(origRowIndex); + } + } else { + for (auto origRowIndex : transitionMatrix.getRowGroupIndices(state)) { + processRow(origRowIndex); + } + } + } + submatrix = matrixBuilder.build(); + + // std::cout << "Submatrix before ec elim:\n" << submatrix << std::endl; + // std::cout << "targetRowValues before ec elim:\n" << storm::utility::vector::toString(targetRowValues) << std::endl; + // std::cout << "conditionRowValues before ec elim:\n" << storm::utility::vector::toString(conditionRowValues) << std::endl; + // eliminate ECs if present. We already checked that the initial state can not yield observation failure, so it cannot be part of an EC. + // For all remaining ECs, staying in an EC forever is reflected by collecting a value of zero for both, target and condition + storm::storage::BitVector allExceptInit(numSubmatrixRowGroups, true); + allExceptInit.set(initialStateInSubmatrix, false); + eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, + conditionRowValues); + // std::cout << "Submatrix after ec elim:\n" << submatrix << std::endl; + // std::cout << "targetRowValues after ec elim:\n" << storm::utility::vector::toString(targetRowValues) << std::endl; + // std::cout << "conditionRowValues after ec elim:\n" << storm::utility::vector::toString(conditionRowValues) << std::endl; + STORM_PRINT_AND_LOG("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " + << submatrix.getEntryCount() << " transitions.\n"); + } + + SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, + ValueType const& conditionWeight) const { + auto rowValues = createScaledVector(targetWeight, targetRowValues, -conditionWeight, conditionRowValues); + + // Initialize the solution vector. + std::vector x(submatrix.getRowGroupCount(), storm::utility::zero()); + + // Set up the solver. + auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(env, submatrix); + solver->setOptimizationDirection(dir); + solver->setRequirementsChecked(); + solver->setHasUniqueSolution(true); + solver->setHasNoEndComponents(true); + solver->setLowerBound(-storm::utility::one()); + solver->setUpperBound(storm::utility::one()); + + // std::cout << "solving equation system with matrix \n" << submatrix << " and row values \n" << storm::utility::vector::toString(rowValues) << + // std::endl; Solve the corresponding system of equations. + solver->solveEquations(env, x, rowValues); + return x[initialStateInSubmatrix]; + } + + private: + std::vector createScaledVector(ValueType const& w1, std::vector const& v1, ValueType const& w2, + std::vector const& v2) const { + STORM_LOG_ASSERT(v1.size() == v2.size(), "Vector sizes must match"); + std::vector result; + result.reserve(v1.size()); + for (size_t i = 0; i < v1.size(); ++i) { + result.push_back(w1 * v1[i] + w2 * v2[i]); + } + return result; + } + + storm::storage::SparseMatrix submatrix; + storm::storage::BitVector rowsWithSum1; + std::vector targetRowValues; + std::vector conditionRowValues; + uint64_t initialStateInSubmatrix; +}; + +template +SolutionType computeViaBinarySearch(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { + SolutionType const precision = storm::utility::convertNumber(env.solver().minMax().getPrecision()); + bool const relative = env.solver().minMax().getRelativeTerminationCriterion(); + + WeightedDiffComputer wdc(initialState, transitionMatrix, normalForm); + SolutionType lowerBound = storm::utility::zero(); + SolutionType upperBound = storm::utility::one(); + storm::Environment absEnv = env; + absEnv.solver().minMax().setRelativeTerminationCriterion(false); + for (uint64_t iterationCount = 1; true; ++iterationCount) { + SolutionType const middle = (lowerBound + upperBound) / 2; + SolutionType const middleValue = wdc.computeWeightedDiff(env, dir, storm::utility::one(), middle); + if (middleValue >= storm::utility::zero()) { + lowerBound = middle; + } + if (middleValue <= storm::utility::zero()) { + upperBound = middle; + } + SolutionType const boundDiff = upperBound - lowerBound; + STORM_LOG_INFO("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(lowerBound) + << ",\n\t Upper bound: " << storm::utility::convertNumber(upperBound) + << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) + << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "\n\n"); + if (boundDiff <= (relative ? (precision * lowerBound) : precision)) { + break; + } + } + return (lowerBound + upperBound) / 2; } } // namespace internal @@ -244,31 +503,43 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // @see doi.org/10.1007/978-3-642-54862-8_43 STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, "Only one initial state is supported for conditional probabilities"); + STORM_PRINT_AND_LOG("Computing conditional probabilities for a model with " << transitionMatrix.getRowGroupCount() << " states and " + << transitionMatrix.getEntryCount() << " transitions.\n"); storm::utility::Stopwatch sw(true); - auto normalFormData = internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, targetStates, conditionStates); - STORM_PRINT_AND_LOG("Time for obtaining the normal form:" << sw << ".\n"); - - sw.restart(); - // Then, we solve the induced problem using the selected algorithm[p + auto normalFormData = + internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), targetStates, conditionStates); + sw.stop(); + STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); + // Then, we solve the induced problem using the selected algorithm auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); - auto const algString = storm::settings::getModule().getConditionalAlgorithm(); if (normalFormData.terminalStates.get(initialState)) { if (normalFormData.conditionStates.get(initialState)) { initialStateValue = normalFormData.targetValue(initialState); // The value is already known, nothing to do. } else { - STORM_LOG_THROW(!normalFormData.observationFailureStates.get(initialState), storm::exceptions::NotSupportedException, + STORM_LOG_THROW(!normalFormData.universalObservationFailureStates.get(initialState), storm::exceptions::NotSupportedException, "Trying to compute undefined conditional probability: the condition has probability 0 under all policies."); // The last case for a terminal initial state is that it is already target and the condition is reachable with non-zero probability. // In this case, all schedulers induce a conditional probability of 1 (or do not reach the condition, i.e., have undefined value) initialStateValue = storm::utility::one(); } - } else if (algString == "restart" || algString == "default") { - initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + STORM_PRINT_AND_LOG("Initial state is terminal.\n"); } else { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); + STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState), "Initial state must be a maybe state if it is not a terminal state"); + auto const algString = storm::settings::getModule().getConditionalAlgorithm(); + STORM_PRINT_AND_LOG("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << algString + << "'.\n"); + sw.restart(); + if (algString == "restart" || algString == "default") { + initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else if (algString == "binary") { + initialStateValue = internal::computeViaBinarySearch(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); + } + sw.stop(); + STORM_PRINT_AND_LOG("Time for analyzing the normal form: " << sw << ".\n"); } - STORM_PRINT_AND_LOG("Time for analyzing the normal form:" << sw << ".\n"); return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); } From bf9ee5b94c7cf3e5c24955bd0d0ff1da59cdace3 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 28 Nov 2024 10:32:14 +0100 Subject: [PATCH 012/102] Fix last bugs --- .../generator/GenerateMonitorVerifier.cpp | 30 ++++++++++--------- .../generator/GenerateMonitorVerifier.h | 8 ++++- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index ca9422922c..2bef4914cc 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -5,13 +5,11 @@ #include #include #include -#include #include #include #include #include #include "storm/adapters/RationalNumberAdapter.h" -#include "storm/exceptions/AbortException.h" #include "storm/exceptions/InvalidArgumentException.h" #include "storm/storage/BitVector.h" #include "storm/storage/SparseMatrix.h" @@ -24,8 +22,9 @@ namespace generator { template MonitorVerifier::MonitorVerifier(const models::sparse::Pomdp& product, - const std::map, uint32_t>& observationMap) - : product(storm::models::sparse::Pomdp(product)), observationMap(observationMap) {} + const std::map, uint32_t>& observationMap, + std::map observationDefaultAction) + : product(storm::models::sparse::Pomdp(product)), observationMap(observationMap), observationDefaultAction(observationDefaultAction) {} template const std::map, uint32_t>& MonitorVerifier::getObservationMap() { @@ -37,6 +36,11 @@ const models::sparse::Pomdp& MonitorVerifier::getProduct() return product; } +template +const std::map& MonitorVerifier::getObservationDefaultAction() { + return observationDefaultAction; +} + template GenerateMonitorVerifier::GenerateMonitorVerifier(models::sparse::Dtmc const& mc, models::sparse::Mdp const& monitor, std::shared_ptr& exprManager, Options const& options) @@ -245,25 +249,23 @@ std::shared_ptr> GenerateMonitorVerifier:: // Calculate which rows belong to action which don't all return for an observation and only keep these storm::storage::SparseMatrix transMatrix = builder.build(); storm::storage::BitVector rowsToKeep(transMatrix.getRowCount()); + std::map observationDefaultAction; u_int32_t currentObservation = 0; for (auto const& actionsInObs : observationUsedActions) { + if (actionsInObs.size() == 1) { + observationDefaultAction[currentObservation] = *actionsInObs.begin(); + } + for (auto const& action : actionsInObs) { // std::cout << "Keeping action obs (" << action << ", " << currentObservation << ")" << std::endl; rowsToKeep |= rowActionObservationMap[std::make_pair(action, currentObservation)]; } currentObservation++; } - // std::cout << "Kept " << rowsToKeep.getNumberOfSetBits() << " out of " << numberOfRows << " rows." << std::endl; + std::cout << "Kept " << rowsToKeep.getNumberOfSetBits() << " out of " << numberOfRows << " rows." << std::endl; + // rowsToKeep.setMultiple(0, numberOfRows); numberOfRows = rowsToKeep.getNumberOfSetBits(); storm::storage::SparseMatrix reducedTransitionMatrix = transMatrix.restrictRows(rowsToKeep); - // rowsToKeep.complement(); - // storm::storage::SparseMatrix inverseReducedTransitionMatrix = transMatrix.restrictRows(rowsToKeep, true); - // for (auto row = 0; row < inverseReducedTransitionMatrix.getRowCount(); ++row) { - // STORM_LOG_THROW(inverseReducedTransitionMatrix.getRow(row).getNumberOfEntries() == prodInitial.size(), storm::exceptions::AbortException, - // "Only dirac rows can be thrown away but " + std::to_string(row) + " is thrown away"); - // } - // rowsToKeep.complement(); - // auto reducedTransitionMatrix = builder.build(); // Create state labeling const state_type numberOfStates = nextStateId; @@ -382,7 +384,7 @@ std::shared_ptr> GenerateMonitorVerifier:: // Store model storm::models::sparse::Pomdp product(std::move(components)); - auto mv = std::make_shared>(std::move(product), std::move(observationMap)); + auto mv = std::make_shared>(std::move(product), std::move(observationMap), std::move(observationDefaultAction)); return mv; } diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.h b/src/storm-pomdp/generator/GenerateMonitorVerifier.h index a632293530..31c06a654f 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.h +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.h @@ -1,4 +1,7 @@ #pragma once +#include +#include +#include #include "storm/models/sparse/Dtmc.h" #include "storm/models/sparse/Mdp.h" #include "storm/models/sparse/Pomdp.h" @@ -8,14 +11,17 @@ namespace storm::generator { template class MonitorVerifier { public: - MonitorVerifier(const storm::models::sparse::Pomdp& product, const std::map, uint32_t>& observationMap); + MonitorVerifier(const storm::models::sparse::Pomdp& product, const std::map, uint32_t>& observationMap, + std::map observationDefaultAction); const std::map, uint32_t>& getObservationMap(); + const std::map& getObservationDefaultAction(); const storm::models::sparse::Pomdp& getProduct(); private: storm::models::sparse::Pomdp product; std::map, uint32_t> observationMap; + std::map observationDefaultAction; }; template From aed50012ce6f52848f10673c7d82a7f9873402c7 Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Mon, 11 Nov 2024 23:22:31 +0100 Subject: [PATCH 013/102] format --- .../transformer/ObservationTraceUnfolder.cpp | 39 ++++++++++--------- .../transformer/ObservationTraceUnfolder.h | 2 +- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index 95bffc752e..295f77299f 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -5,7 +5,6 @@ #include "storm/storage/expressions/ExpressionManager.h" #include "storm/utility/ConstantsComparator.h" - #undef _VERBOSE_OBSERVATION_UNFOLDING namespace storm { @@ -50,20 +49,21 @@ std::shared_ptr> ObservationTraceUnfolder< svbuilder.addVariable(svvar); svbuilder.addVariable(tsvar); - // TODO: Do we need this as ordered maps? Is it better to make them unordered? - std::map unfoldedToOld; - std::map unfoldedToOldNextStep; - std::map oldToUnfolded; + std::unordered_map unfoldedToOld; + std::unordered_map unfoldedToOldNextStep; + std::unordered_map oldToUnfolded; #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << "start buildiing matrix...\n"; #endif uint64_t newStateIndex = 0; - // TODO do not add violated state if we do rejection sampling. uint64_t violatedState = newStateIndex; - ++newStateIndex; - // Add this initial state state: + if (!options.rejectionSampling) { + // The violated state is only used if we do no use the rejection semantics. + ++newStateIndex; + } + // Add this initial state: uint64_t initialState = newStateIndex; ++newStateIndex; @@ -73,10 +73,12 @@ std::shared_ptr> ObservationTraceUnfolder< storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, true, true); // TODO only add this state if it is actually reachable / rejection sampling - // the violated state is a sink state - transitionMatrixBuilder.newRowGroup(violatedState); - transitionMatrixBuilder.addNextValue(violatedState, violatedState, storm::utility::one()); - svbuilder.addState(violatedState, {}, {-1, -1}); + if (!options.rejectionSampling) { + // the violated state (only used when no rejection sampling) is a sink state + transitionMatrixBuilder.newRowGroup(violatedState); + transitionMatrixBuilder.addNextValue(violatedState, violatedState, storm::utility::one()); + svbuilder.addState(violatedState, {}, {-1, -1}); + } // Now we are starting to build the MDP from the initial state onwards. uint64_t newRowGroupStart = initialState; @@ -187,14 +189,14 @@ std::shared_ptr> ObservationTraceUnfolder< #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << components.transitionMatrix << '\n'; #endif - STORM_LOG_ASSERT(components.transitionMatrix.getRowGroupCount() == targetState + 2, - "Expect row group count (" << components.transitionMatrix.getRowGroupCount() << ") one more as target state index " << targetState << ")"); storm::models::sparse::StateLabeling labeling(components.transitionMatrix.getRowGroupCount()); labeling.addLabel("_goal"); labeling.addLabelToState("_goal", targetState); - labeling.addLabel("_violated"); - labeling.addLabelToState("_violated", violatedState); + if (!options.rejectionSampling) { + labeling.addLabel("_violated"); + labeling.addLabelToState("_violated", violatedState); + } labeling.addLabel("_end"); labeling.addLabelToState("_end", sinkState); labeling.addLabelToState("_end", targetState); @@ -206,8 +208,8 @@ std::shared_ptr> ObservationTraceUnfolder< } template -std::shared_ptr> ObservationTraceUnfolder::extend(uint32_t observation) { - traceSoFar.push_back(observation); +std::shared_ptr> ObservationTraceUnfolder::extend(std::vector const& observations) { + traceSoFar.insert(traceSoFar.end(), observations.begin(), observations.end()); return transform(traceSoFar); } @@ -224,5 +226,6 @@ bool ObservationTraceUnfolder::isRejectionSamplingSet() const { template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; +template class ObservationTraceUnfolder; } // namespace pomdp } // namespace storm diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h index c5b2c6625b..55fce6e727 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h @@ -35,7 +35,7 @@ class ObservationTraceUnfolder { * @param observation * @return */ - std::shared_ptr> extend(uint32_t observation); + std::shared_ptr> extend(std::vector const& observations); /** * When using the incremental approach, reset the observations made so far. * @param observation The new initial observation From f41b33734851f44efdf12fe0a7e18b8942e1a8e4 Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Tue, 14 Jan 2025 11:37:29 +0100 Subject: [PATCH 014/102] Update src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp Co-authored-by: Tim Quatmann --- src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index 295f77299f..18f93467cf 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -58,18 +58,18 @@ std::shared_ptr> ObservationTraceUnfolder< #endif uint64_t newStateIndex = 0; - uint64_t violatedState = newStateIndex; + uint64_t const violatedState = newStateIndex; if (!options.rejectionSampling) { // The violated state is only used if we do no use the rejection semantics. ++newStateIndex; } // Add this initial state: - uint64_t initialState = newStateIndex; + uint64_t const initialState = newStateIndex; ++newStateIndex; unfoldedToOldNextStep[initialState] = actualInitialStates.getNextSetIndex(0); - uint64_t resetDestination = options.rejectionSampling ? initialState : violatedState; // Should be initial state for the standard semantics. + uint64_t const resetDestination = options.rejectionSampling ? initialState : violatedState; // Should be initial state for the standard semantics. storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, true, true); // TODO only add this state if it is actually reachable / rejection sampling From 5221712d3650b8332cd2974d0a5f320b1afe9b4d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 16 Jan 2025 18:01:15 +0100 Subject: [PATCH 015/102] updates --- .../generator/GenerateMonitorVerifier.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index 2bef4914cc..b3bc617c20 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -10,6 +10,7 @@ #include #include #include "storm/adapters/RationalNumberAdapter.h" +#include "storm/exceptions/IllegalArgumentException.h" #include "storm/exceptions/InvalidArgumentException.h" #include "storm/storage/BitVector.h" #include "storm/storage/SparseMatrix.h" @@ -222,8 +223,16 @@ std::shared_ptr> GenerateMonitorVerifier:: if (monitor.getStateLabeling().getStateHasLabel(options.acceptingLabel, mon_from)) { if (options.useRisk) { - builder.addNextValue(currentRow, goalIndex, risk[mc_from]); - builder.addNextValue(currentRow, stopIndex, utility::one() - risk[mc_from]); + STORM_LOG_THROW(risk[mc_from] >= -utility::convertNumber(1e-12) && risk[mc_from] <= utility::convertNumber(1.0 + 1e-12), + exceptions::IllegalArgumentException, "Risk for state " + std::to_string(mc_from) + " is not in [0, 1]"); + if (utility::isAlmostZero(risk[mc_from])) { + builder.addNextValue(currentRow, stopIndex, utility::one()); + } else if (utility::isAlmostOne(risk[mc_from])) { + builder.addNextValue(currentRow, goalIndex, utility::one()); + } else { + builder.addNextValue(currentRow, goalIndex, risk[mc_from]); + builder.addNextValue(currentRow, stopIndex, utility::one() - risk[mc_from]); + } } else { if (mc.getStateLabeling().getStateHasLabel(options.goodLabel, mc_from)) { builder.addNextValue(currentRow, goalIndex, utility::one()); From 21363afae4ca1176516eedd2e7a9119860d797c1 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sun, 17 Nov 2024 07:21:57 +0100 Subject: [PATCH 016/102] Re-implementation of restart method for conditional probabilities for MDPs --- .../helper/conditional/ConditionalHelper.cpp | 282 ++++++++++++++++++ .../helper/conditional/ConditionalHelper.h | 30 ++ .../prctl/SparseMdpPrctlModelChecker.cpp | 12 +- .../settings/modules/ModelCheckerSettings.cpp | 11 + .../settings/modules/ModelCheckerSettings.h | 3 + 5 files changed, 334 insertions(+), 4 deletions(-) create mode 100644 src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp create mode 100644 src/storm/modelchecker/helper/conditional/ConditionalHelper.h diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp new file mode 100644 index 0000000000..9d4676a8e2 --- /dev/null +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -0,0 +1,282 @@ +#include "storm/modelchecker/helper/conditional/ConditionalHelper.h" + +#include "storm/adapters/RationalNumberAdapter.h" +#include "storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h" +#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" +#include "storm/solver/SolveGoal.h" +#include "storm/storage/BitVector.h" +#include "storm/storage/MaximalEndComponentDecomposition.h" +#include "storm/storage/SparseMatrix.h" +#include "storm/transformer/EndComponentEliminator.h" +#include "storm/utility/graph.h" +#include "storm/utility/macros.h" + +#include "storm/exceptions/NotImplementedException.h" +#include "storm/exceptions/NotSupportedException.h" + +#include "storm/settings/SettingsManager.h" +#include "storm/settings/modules/ModelCheckerSettings.h" + +namespace storm::modelchecker { + +namespace internal { + +template +SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix&& matrix, std::vector&& rowValues, + storm::OptionalRef const& rowsWithSum1, storm::solver::OptimizationDirection const dir, + uint64_t const initialState) { + if (rowsWithSum1.has_value()) { + storm::storage::BitVector const allRowGroups(matrix.getRowGroupCount(), true); + storm::storage::BitVector const noRowGroups(matrix.getRowGroupCount(), false); + storm::storage::MaximalEndComponentDecomposition mecs(matrix, matrix.transpose(true), allRowGroups, *rowsWithSum1); + if (!mecs.empty()) { + auto ecElimResult = storm::transformer::EndComponentEliminator::transform(matrix, mecs, allRowGroups, noRowGroups); + std::vector newRowValues; + newRowValues.reserve(ecElimResult.newToOldRowMapping.size()); + for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { + newRowValues.push_back(rowValues[oldRowIndex]); + } + return solveMinMaxEquationSystem(env, std::move(ecElimResult.matrix), std::move(newRowValues), storm::NullRef, dir, + ecElimResult.oldToNewStateMapping[initialState]); + } + } + + // Initialize the solution vector. + std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); + + // Set up the solver. + auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create( + env, std::forward>(matrix)); + solver->setOptimizationDirection(dir); + solver->setRequirementsChecked(); + solver->setHasUniqueSolution(true); + solver->setHasNoEndComponents(true); + solver->setLowerBound(storm::utility::zero()); + solver->setUpperBound(storm::utility::one()); + + // Solve the corresponding system of equations. + solver->solveEquations(env, x, rowValues); + return x[initialState]; +} + +/*! + * Computes the reachability probabilities for the given target states and inserts all non-zero values into the given map. + * The assumption is that usually, not all states are reachable from the initial states. + */ +template +void computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, + storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { + if (initialStates.empty()) { // nothing to do + return; + } + auto const reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, allowedStates, targetStates); + auto const subTargets = targetStates % reachableStates; + // Catch the case where no target is reachable from an initial state. In this case, there is nothing to do since all probabilities are zero. + if (subTargets.empty()) { + return; + } + auto const subInits = initialStates % reachableStates; + auto const submatrix = transitionMatrix.getSubmatrix(true, reachableStates, reachableStates); + // TODO: adapt precision in sound mode + auto const subResult = helper::SparseMdpPrctlHelper::computeUntilProbabilities( + env, storm::solver::SolveGoal(dir, subInits), submatrix, submatrix.transpose(true), storm::storage::BitVector(subTargets.size(), true), + subTargets, false, false); + auto origInitIt = initialStates.begin(); + for (auto subInit : subInits) { + auto const& val = subResult.values[subInit]; + if (!storm::utility::isZero(val)) { + nonZeroResults.emplace(*origInitIt, val); + } + ++origInitIt; + } +} + +template +struct NormalFormData { + storm::storage::BitVector const + definedStates; // Those states where the property is defined, i.e., the condition states can be reached with positive probability + storm::storage::BitVector const terminalStates; // Those states where we already know the probability to reach the condition and the target value + storm::storage::BitVector const conditionStates; // Those states where the condition holds almost surely (under all schedulers) + storm::storage::BitVector const observationFailureStates; // Those states where the condition is not reachable (under all schedulers) + std::map const nonZeroTargetStateValues; // The known non-zero target values. (default is zero) + // There are three cases of terminal states: + // 1. conditionStates: The condition holds, so the target value is the optimal probability to reach target from there + // 2. targetStates: The target is reached, so the target value is the optimal probability to reach a condition from there. + // The remaining probability mass is the probability of an observation failure + // 3. states that can not reach the condition under any scheduler. The target value is zero. + + // TerminalStates is a superset of conditionStates and dom(nonZeroTargetStateValues). + // For a terminalState that is not a conditionState, it is impossible to (reach the condition and not reach the target). + + ValueType targetValue(uint64_t state) const { + STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get target value for non-terminal state"); + auto const it = nonZeroTargetStateValues.find(state); + return it == nonZeroTargetStateValues.end() ? storm::utility::zero() : it->second; + } + + ValueType failProbability(uint64_t state) const { + STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get fail probability for non-terminal state"); + STORM_LOG_ASSERT(!conditionStates.get(state), "Tried to get fail probability for a condition state"); + // condition states have fail probability zero + return storm::utility::one() - targetValue(state); + } +}; + +template +NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, + storm::storage::BitVector const& conditionStates) { + storm::storage::BitVector const allStates(transitionMatrix.getRowGroupCount(), true); + auto extendedConditionStates = + storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); + auto observationFailureStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); + std::map nonZeroTargetStateValues; + auto const extendedTargetStates = + storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, targetStates); + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); + auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | observationFailureStates); + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + + auto terminalStates = extendedConditionStates | extendedTargetStates | observationFailureStates; + + if (storm::solver::minimize(dir)) { + // There can be targetAndNotCondFailStates from which only the *minimal* probability to reach a condition is zero. + // For those states, the optimal policy is to enforce observation failure. + // States that can only reach (target states with almost sure observation failure) or observation failure will be treated as terminal states with + // targetValue zero and failProbability one. + + // We first determine states where the optimal policy reaches the condition with positive probability + auto terminalStatesThatReachCondition = extendedConditionStates; + for (auto state : targetAndNotCondFailStates) { + if (nonZeroTargetStateValues.contains(state)) { + terminalStatesThatReachCondition.set(state, true); + } + } + // Then, we determine the non-terminal states that cannot reach such states. + terminalStates |= storm::utility::graph::performProb0A(backwardTransitions, ~terminalStates, terminalStatesThatReachCondition); + } + + return NormalFormData{.terminalStates = std::move(terminalStates), + .conditionStates = std::move(extendedConditionStates), + .observationFailureStates = std::move(observationFailureStates), + .nonZeroTargetStateValues = std::move(nonZeroTargetStateValues)}; +} + +/*! + * Uses the restart method by Baier et al. +// @see doi.org/10.1007/978-3-642-54862-8_43 + */ +template +SolutionType computeViaRestartMethod(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { + auto const maybeStates = ~normalForm.terminalStates; + auto const stateToMatrixIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); + auto const numMaybeStates = maybeStates.getNumberOfSetBits(); + auto const numMaybeChoices = transitionMatrix.getNumRowsInRowGroups(maybeStates); + + // Build the transitions that include a backwards loop to the initial state + storm::storage::SparseMatrixBuilder matrixBuilder(numMaybeChoices, numMaybeStates, 0, true, true, numMaybeStates); + std::vector rowValues; + storm::storage::BitVector rowsWithSum1(numMaybeChoices, true); + rowValues.reserve(numMaybeChoices); + uint64_t currentRow = 0; + for (auto state : maybeStates) { + matrixBuilder.newRowGroup(currentRow); + for (auto origRowIndex : transitionMatrix.getRowGroupIndices(state)) { + // We make two passes over the successors. First, we find out the reset probabilities and target probabilities + // Then, we insert the matrix entries in the correct order + // This two-phase approach is to avoid a costly out-of-order insertion into the matrix + ValueType targetProbability = storm::utility::zero(); + ValueType restartProbability = storm::utility::zero(); + bool rowSumIsLess1 = false; + for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { + if (normalForm.terminalStates.get(entry.getColumn())) { + ValueType const targetValue = normalForm.targetValue(entry.getColumn()); + targetProbability += targetValue * entry.getValue(); + if (normalForm.conditionStates.get(entry.getColumn())) { + rowSumIsLess1 = true; + } else { + if (!storm::utility::isZero(targetValue)) { + rowSumIsLess1 = true; + } + restartProbability += entry.getValue() * normalForm.failProbability(entry.getColumn()); + } + } + } + if (rowSumIsLess1) { + rowsWithSum1.set(currentRow, false); + } + rowValues.push_back(targetProbability); + bool addRestartTransition = !storm::utility::isZero(restartProbability); + for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { + // Insert backloop probability if we haven't done so yet and are past the initial state index + // This is to avoid a costly out-of-order insertion into the matrix + if (addRestartTransition && entry.getColumn() > initialState) { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[initialState], restartProbability); + addRestartTransition = false; + } + if (maybeStates.get(entry.getColumn())) { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[entry.getColumn()], entry.getValue()); + } + } + // Add the backloop if we haven't done this already + if (addRestartTransition) { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[initialState], restartProbability); + } + ++currentRow; + } + } + + return solveMinMaxEquationSystem(env, matrixBuilder.build(), std::move(rowValues), rowsWithSum1, dir, stateToMatrixIndexMap[initialState]); +} + +} // namespace internal + +template +std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { + // We first translate the problem into a normal form. + // @see doi.org/10.1007/978-3-642-54862-8_43 + STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, + "Only one initial state is supported for conditional probabilities"); + auto normalFormData = internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, targetStates, conditionStates); + + // Then, we solve the induced problem using the selected algorithm. + auto const initialState = *goal.relevantValues().begin(); + ValueType initialStateValue = -storm::utility::one(); + auto const algString = storm::settings::getModule().getConditionalAlgorithm(); + if (normalFormData.terminalStates.get(initialState)) { + if (normalFormData.conditionStates.get(initialState)) { + initialStateValue = normalFormData.targetValue(initialState); // The value is already known, nothing to do. + } else { + STORM_LOG_THROW(!normalFormData.observationFailureStates.get(initialState), storm::exceptions::NotSupportedException, + "Trying to compute undefined conditional probability: the condition has probability 0 under all policies."); + // The last case for a terminal initial state is that it is already target and the condition is reachable with non-zero probability. + // In this case, all schedulers induce a conditional probability of 1 (or do not reach the condition, i.e., have undefined value) + initialStateValue = storm::utility::one(); + } + } else if (algString == "restart" || algString == "default") { + initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); + } + return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); +} + +template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, + storm::storage::BitVector const& conditionStates); + +template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, + storm::storage::BitVector const& conditionStates); + +} // namespace storm::modelchecker diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.h b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h new file mode 100644 index 0000000000..12e8c0791e --- /dev/null +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "storm/solver/SolveGoal.h" + +namespace storm { +class Environment; + +namespace storage { +class BitVector; +template +class SparseMatrix; +} // namespace storage + +namespace modelchecker { +class CheckResult; + +namespace utility { +template +class BackwardTransitionCache; +} + +template +std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates); + +} // namespace modelchecker +} // namespace storm diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index a82243a142..8441c324bc 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -3,6 +3,7 @@ #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/InvalidStateException.h" #include "storm/logic/FragmentSpecification.h" +#include "storm/modelchecker/helper/conditional/ConditionalHelper.h" #include "storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h" #include "storm/modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h" #include "storm/modelchecker/helper/ltl/SparseLTLHelper.h" @@ -273,10 +274,13 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - - return storm::modelchecker::helper::SparseMdpPrctlHelper::computeConditionalProbabilities( - env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), - this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + if constexpr (std::is_same_v) { + throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; + } else { + return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), + this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), + leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + } } template diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index 5c54a91e31..bb5060ea09 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -14,6 +14,7 @@ namespace modules { const std::string ModelCheckerSettings::moduleName = "modelchecker"; const std::string ModelCheckerSettings::filterRewZeroOptionName = "filterrewzero"; const std::string ModelCheckerSettings::ltl2daToolOptionName = "ltl2datool"; +const std::string ModelCheckerSettings::conditionalAlgorithmOptionName = "conditional"; ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, filterRewZeroOptionName, false, @@ -27,6 +28,10 @@ ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { "filename", "A script that can be called with a prefix formula and a name for the output automaton.") .build()) .build()); + this->addOption(storm::settings::OptionBuilder(moduleName, conditionalAlgorithmOptionName, false, "The used algorithm for conditional probabilities.") + .setIsAdvanced() + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("alg", "name.").build()) + .build()); } bool ModelCheckerSettings::isFilterRewZeroSet() const { @@ -41,6 +46,12 @@ std::string ModelCheckerSettings::getLtl2daTool() const { return this->getOption(ltl2daToolOptionName).getArgumentByName("filename").getValueAsString(); } +std::string ModelCheckerSettings::getConditionalAlgorithm() const { // TODO + return this->getOption(conditionalAlgorithmOptionName).getHasOptionBeenSet() + ? this->getOption(conditionalAlgorithmOptionName).getArgumentByName("alg").getValueAsString() + : "default"; +} + } // namespace modules } // namespace settings } // namespace storm diff --git a/src/storm/settings/modules/ModelCheckerSettings.h b/src/storm/settings/modules/ModelCheckerSettings.h index 1679289e0c..3ffb7a6eb4 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.h +++ b/src/storm/settings/modules/ModelCheckerSettings.h @@ -35,6 +35,8 @@ class ModelCheckerSettings : public ModuleSettings { */ std::string getLtl2daTool() const; + std::string getConditionalAlgorithm() const; // TODO: do this properly + // The name of the module. static const std::string moduleName; @@ -42,6 +44,7 @@ class ModelCheckerSettings : public ModuleSettings { // Define the string names of the options as constants. static const std::string filterRewZeroOptionName; static const std::string ltl2daToolOptionName; + static const std::string conditionalAlgorithmOptionName; }; } // namespace modules From cf58ea91cd7d5b7665bc9e729efd06571d39bcc1 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 20 Nov 2024 11:45:15 +0100 Subject: [PATCH 017/102] Time measurements for conditional probability computation --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 9d4676a8e2..4c345ad360 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -8,6 +8,7 @@ #include "storm/storage/MaximalEndComponentDecomposition.h" #include "storm/storage/SparseMatrix.h" #include "storm/transformer/EndComponentEliminator.h" +#include "storm/utility/Stopwatch.h" #include "storm/utility/graph.h" #include "storm/utility/macros.h" @@ -243,9 +244,12 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // @see doi.org/10.1007/978-3-642-54862-8_43 STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, "Only one initial state is supported for conditional probabilities"); + storm::utility::Stopwatch sw(true); auto normalFormData = internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, targetStates, conditionStates); + STORM_PRINT_AND_LOG("Time for obtaining the normal form:" << sw << ".\n"); - // Then, we solve the induced problem using the selected algorithm. + sw.restart(); + // Then, we solve the induced problem using the selected algorithm[p auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); auto const algString = storm::settings::getModule().getConditionalAlgorithm(); @@ -264,6 +268,7 @@ std::unique_ptr computeConditionalProbabilities(Environment const& } else { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); } + STORM_PRINT_AND_LOG("Time for analyzing the normal form:" << sw << ".\n"); return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); } From 0625550b1ed25f9f445a4c4066076ca14efc264d Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 27 Nov 2024 14:25:02 +0100 Subject: [PATCH 018/102] First version of binary approach --- .../helper/conditional/ConditionalHelper.cpp | 381 +++++++++++++++--- 1 file changed, 326 insertions(+), 55 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 4c345ad360..7aedab0352 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -1,6 +1,10 @@ +#include +#include + #include "storm/modelchecker/helper/conditional/ConditionalHelper.h" #include "storm/adapters/RationalNumberAdapter.h" +#include "storm/environment/solver/MinMaxSolverEnvironment.h" #include "storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/solver/SolveGoal.h" @@ -22,32 +26,72 @@ namespace storm::modelchecker { namespace internal { -template -SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix&& matrix, std::vector&& rowValues, - storm::OptionalRef const& rowsWithSum1, storm::solver::OptimizationDirection const dir, - uint64_t const initialState) { - if (rowsWithSum1.has_value()) { - storm::storage::BitVector const allRowGroups(matrix.getRowGroupCount(), true); - storm::storage::BitVector const noRowGroups(matrix.getRowGroupCount(), false); - storm::storage::MaximalEndComponentDecomposition mecs(matrix, matrix.transpose(true), allRowGroups, *rowsWithSum1); - if (!mecs.empty()) { - auto ecElimResult = storm::transformer::EndComponentEliminator::transform(matrix, mecs, allRowGroups, noRowGroups); - std::vector newRowValues; - newRowValues.reserve(ecElimResult.newToOldRowMapping.size()); - for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { - newRowValues.push_back(rowValues[oldRowIndex]); - } - return solveMinMaxEquationSystem(env, std::move(ecElimResult.matrix), std::move(newRowValues), storm::NullRef, dir, - ecElimResult.oldToNewStateMapping[initialState]); +template +void eliminateEndComponents(storm::storage::BitVector possibleEcStates, bool addRowAtRepresentativeState, std::optional representativeRowEntry, + storm::storage::SparseMatrix& matrix, uint64_t& initialState, storm::storage::BitVector& rowsWithSum1, + std::vector& rowValues1, storm::OptionalRef> rowValues2 = {}) { + storm::storage::MaximalEndComponentDecomposition ecs(matrix, matrix.transpose(true), possibleEcStates, rowsWithSum1); + if (ecs.empty()) { + return; // nothing to do + } + + storm::storage::BitVector allRowGroups(matrix.getRowGroupCount(), true); + auto ecElimResult = storm::transformer::EndComponentEliminator::transform( + matrix, ecs, allRowGroups, addRowAtRepresentativeState ? allRowGroups : ~allRowGroups, representativeRowEntry.has_value()); + + // Update matrix + matrix = std::move(ecElimResult.matrix); + if (addRowAtRepresentativeState && representativeRowEntry) { + auto const columnIndex = ecElimResult.oldToNewStateMapping[*representativeRowEntry]; + for (auto representativeRowIndex : ecElimResult.sinkRows) { + auto row = matrix.getRow(representativeRowIndex); + STORM_LOG_ASSERT(row.getNumberOfEntries() == 1, "unexpected number of entries in representative row."); + auto& entry = *row.begin(); + entry.setColumn(columnIndex); + } + } + + // update vectors + auto updateRowValue = [&ecElimResult](std::vector& rowValues) { + std::vector newRowValues; + newRowValues.reserve(ecElimResult.newToOldRowMapping.size()); + for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { + newRowValues.push_back(rowValues[oldRowIndex]); } + rowValues = std::move(newRowValues); + STORM_LOG_ASSERT( + std::all_of(ecElimResult.sinkRows.begin(), ecElimResult.sinkRows.end(), [&rowValues](auto i) { return storm::utility::isZero(rowValues[i]); }), + "Sink rows are expected to have zero value"); + }; + updateRowValue(rowValues1); + if (rowValues2) { + updateRowValue(*rowValues2); } + // update initial state + initialState = ecElimResult.oldToNewStateMapping[initialState]; + + // update bitvector + storm::storage::BitVector newRowsWithSum1(ecElimResult.newToOldRowMapping.size(), true); + uint64_t newRowIndex = 0; + for (auto oldRowIndex : ecElimResult.newToOldRowMapping) { + if ((addRowAtRepresentativeState && !representativeRowEntry.has_value() && ecElimResult.sinkRows.get(newRowIndex)) || !rowsWithSum1.get(oldRowIndex)) { + newRowsWithSum1.set(newRowIndex, false); + } + ++newRowIndex; + } + rowsWithSum1 = std::move(newRowsWithSum1); +} + +template +SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, + std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, + storm::solver::OptimizationDirection const dir, uint64_t const initialState) { // Initialize the solution vector. std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); // Set up the solver. - auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create( - env, std::forward>(matrix)); + auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(env, matrix); solver->setOptimizationDirection(dir); solver->setRequirementsChecked(); solver->setHasUniqueSolution(true); @@ -95,12 +139,13 @@ void computeReachabilityProbabilities(Environment const& env, std::map struct NormalFormData { - storm::storage::BitVector const - definedStates; // Those states where the property is defined, i.e., the condition states can be reached with positive probability - storm::storage::BitVector const terminalStates; // Those states where we already know the probability to reach the condition and the target value - storm::storage::BitVector const conditionStates; // Those states where the condition holds almost surely (under all schedulers) - storm::storage::BitVector const observationFailureStates; // Those states where the condition is not reachable (under all schedulers) - std::map const nonZeroTargetStateValues; // The known non-zero target values. (default is zero) + storm::storage::BitVector const maybeStates; // Those states that can be reached from initial without reaching a terminal state + storm::storage::BitVector const terminalStates; // Those states where we already know the probability to reach the condition and the target value + storm::storage::BitVector const conditionStates; // Those states where the condition holds almost surely (under all schedulers) + storm::storage::BitVector const universalObservationFailureStates; // Those states where the condition is not reachable (under all schedulers) + storm::storage::BitVector const existentialObservationFailureStates; // Those states s where a scheduler exists that (i) does not reach the condition from + // s and (ii) acts optimal in all terminal states + std::map const nonZeroTargetStateValues; // The known non-zero target values. (default is zero) // There are three cases of terminal states: // 1. conditionStates: The condition holds, so the target value is the optimal probability to reach target from there // 2. targetStates: The target is reached, so the target value is the optimal probability to reach a condition from there. @@ -127,41 +172,50 @@ struct NormalFormData { template NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, - storm::storage::BitVector const& conditionStates) { + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& relevantStates, + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { storm::storage::BitVector const allStates(transitionMatrix.getRowGroupCount(), true); auto extendedConditionStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); - auto observationFailureStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); + auto universalObservationFailureStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); std::map nonZeroTargetStateValues; auto const extendedTargetStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, targetStates); computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); - auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | observationFailureStates); + auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates); computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); - auto terminalStates = extendedConditionStates | extendedTargetStates | observationFailureStates; + auto terminalStates = extendedConditionStates | extendedTargetStates | universalObservationFailureStates; + + // get states where the optimal policy reaches the condition with positive probability + auto terminalStatesThatReachCondition = extendedConditionStates; + for (auto state : targetAndNotCondFailStates) { + if (nonZeroTargetStateValues.contains(state)) { + terminalStatesThatReachCondition.set(state, true); + } + } if (storm::solver::minimize(dir)) { - // There can be targetAndNotCondFailStates from which only the *minimal* probability to reach a condition is zero. + // There can be target states from which (only) the *minimal* probability to reach a condition is zero. // For those states, the optimal policy is to enforce observation failure. // States that can only reach (target states with almost sure observation failure) or observation failure will be treated as terminal states with // targetValue zero and failProbability one. - - // We first determine states where the optimal policy reaches the condition with positive probability - auto terminalStatesThatReachCondition = extendedConditionStates; - for (auto state : targetAndNotCondFailStates) { - if (nonZeroTargetStateValues.contains(state)) { - terminalStatesThatReachCondition.set(state, true); - } - } - // Then, we determine the non-terminal states that cannot reach such states. terminalStates |= storm::utility::graph::performProb0A(backwardTransitions, ~terminalStates, terminalStatesThatReachCondition); } - return NormalFormData{.terminalStates = std::move(terminalStates), + auto nonTerminalStates = ~terminalStates; + + auto existentialObservationFailureStates = storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), + backwardTransitions, nonTerminalStates, terminalStatesThatReachCondition); + + // Restrict non-terminal states to those that are still relevant + nonTerminalStates &= storm::utility::graph::getReachableStates(transitionMatrix, relevantStates, nonTerminalStates, terminalStates); + + return NormalFormData{.maybeStates = std::move(nonTerminalStates), + .terminalStates = std::move(terminalStates), .conditionStates = std::move(extendedConditionStates), - .observationFailureStates = std::move(observationFailureStates), + .universalObservationFailureStates = std::move(universalObservationFailureStates), + .existentialObservationFailureStates = std::move(existentialObservationFailureStates), .nonZeroTargetStateValues = std::move(nonZeroTargetStateValues)}; } @@ -172,7 +226,7 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver template SolutionType computeViaRestartMethod(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { - auto const maybeStates = ~normalForm.terminalStates; + auto const& maybeStates = normalForm.maybeStates; auto const stateToMatrixIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); auto const numMaybeStates = maybeStates.getNumberOfSetBits(); auto const numMaybeChoices = transitionMatrix.getNumRowsInRowGroups(maybeStates); @@ -230,7 +284,212 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init } } - return solveMinMaxEquationSystem(env, matrixBuilder.build(), std::move(rowValues), rowsWithSum1, dir, stateToMatrixIndexMap[initialState]); + auto matrix = matrixBuilder.build(); + auto initStateInMatrix = stateToMatrixIndexMap[initialState]; + + // Eliminate end components in two phases + // First, we catch all end components that do not contain the initial state. It is possible to stay in those ECs forever + // without reaching the condition. This is reflected by a backloop to the initial state. + storm::storage::BitVector selectedStatesInMatrix(numMaybeChoices, true); + selectedStatesInMatrix.set(initStateInMatrix, false); + eliminateEndComponents(selectedStatesInMatrix, true, initStateInMatrix, matrix, initStateInMatrix, rowsWithSum1, rowValues); + // Second, eliminate the remaining ECs. These must involve the initial state and might have been introduced in the previous step. + // A policy selecting such an EC must reach the condition with probability zero and is thus invalid. + selectedStatesInMatrix.set(initStateInMatrix, true); + eliminateEndComponents(selectedStatesInMatrix, false, std::nullopt, matrix, initStateInMatrix, rowsWithSum1, rowValues); + + STORM_PRINT_AND_LOG("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " + << matrix.getEntryCount() << " transitions.\n"); + // Finally, solve the equation system + return solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); +} + +template +class WeightedDiffComputer { + public: + WeightedDiffComputer(uint64_t const initialState, storm::storage::SparseMatrix const& transitionMatrix, + NormalFormData const& normalForm) { + // Determine rowgroups (states) and rows (choices) of the submatrix + auto subMatrixRowGroups = normalForm.maybeStates; + // Identify and eliminate the initial component to enforce that it is eventually exited + // The initial component is the largest subset of maybestates C such that + // (i) the initial state is contained in C + // (ii) each state in C can be reached from the initial state while only playing actions that stay inside C or observation failure and + // (iii) for each state in C except the initial state there is a policy that almost surely reaches an observation failure + // An optimal scheduler can intuitively pick the best exiting action of C and enforce that all paths that satisfy the condition exit C through that + // action. By eliminating the initial component, we ensure that only policies that actually exit C are considered. The remaining policies have + // probability zero of satisfying the condition. + storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); + subMatrixRowGroups.set(initialState, false); // temporarily unset initial state + std::vector dfsStack = {initialState}; + while (!dfsStack.empty()) { + auto const state = dfsStack.back(); + dfsStack.pop_back(); + for (auto rowIndex : transitionMatrix.getRowGroupIndices(state)) { + auto const row = transitionMatrix.getRow(rowIndex); + if (std::all_of(row.begin(), row.end(), + [&normalForm](auto const& entry) { return normalForm.existentialObservationFailureStates.get(entry.getColumn()); })) { + for (auto const& entry : row) { + auto const& successor = entry.getColumn(); + if (subMatrixRowGroups.get(successor)) { + subMatrixRowGroups.set(successor, false); + dfsStack.push_back(successor); + } + } + } else { + initialComponentExitRows.set(rowIndex, true); + } + } + } + auto const numSubmatrixRows = transitionMatrix.getNumRowsInRowGroups(subMatrixRowGroups) + initialComponentExitRows.getNumberOfSetBits(); + subMatrixRowGroups.set(initialState, true); // set initial state again, as single representative state for the initial component + auto const numSubmatrixRowGroups = subMatrixRowGroups.getNumberOfSetBits(); + + // state index mapping and initial state + auto stateToMatrixIndexMap = subMatrixRowGroups.getNumberOfSetBitsBeforeIndices(); + initialStateInSubmatrix = stateToMatrixIndexMap[initialState]; + auto const eliminatedInitialComponentStates = normalForm.maybeStates & ~subMatrixRowGroups; + for (auto state : eliminatedInitialComponentStates) { + stateToMatrixIndexMap[state] = initialStateInSubmatrix; // map all eliminated states to the initial state + } + + // build matrix, rows that sum up to 1, target values, condition values + storm::storage::SparseMatrixBuilder matrixBuilder(numSubmatrixRows, numSubmatrixRowGroups, 0, true, true, numSubmatrixRowGroups); + rowsWithSum1 = storm::storage::BitVector(numSubmatrixRows, true); + targetRowValues.reserve(numSubmatrixRows); + conditionRowValues.reserve(numSubmatrixRows); + uint64_t currentRow = 0; + for (auto state : subMatrixRowGroups) { + matrixBuilder.newRowGroup(currentRow); + + // Put the row processing into a lambda for avoiding code duplications + auto processRow = [&](uint64_t origRowIndex) { + // Find out the target and condition probabilities for this row + ValueType targetProbability = storm::utility::zero(); + ValueType conditionProbability = storm::utility::zero(); + bool rowSumIsLess1 = false; + for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { + if (normalForm.terminalStates.get(entry.getColumn())) { + STORM_LOG_ASSERT(!storm::utility::isZero(entry.getValue()), "Transition probability must be non-zero"); + rowSumIsLess1 = true; + ValueType const scaledTargetValue = normalForm.targetValue(entry.getColumn()) * entry.getValue(); + targetProbability += scaledTargetValue; + if (normalForm.conditionStates.get(entry.getColumn())) { + conditionProbability += entry.getValue(); // conditionValue of successor is 1 + } else { + conditionProbability += scaledTargetValue; // for terminal, non-condition states, the condition value equals the target value + } + } else { + matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[entry.getColumn()], entry.getValue()); + } + } + if (rowSumIsLess1) { + rowsWithSum1.set(currentRow, false); + } + targetRowValues.push_back(targetProbability); + conditionRowValues.push_back(conditionProbability); + ++currentRow; + }; + // invoke the lambda + if (state == initialState) { + for (auto origRowIndex : initialComponentExitRows) { + processRow(origRowIndex); + } + } else { + for (auto origRowIndex : transitionMatrix.getRowGroupIndices(state)) { + processRow(origRowIndex); + } + } + } + submatrix = matrixBuilder.build(); + + // std::cout << "Submatrix before ec elim:\n" << submatrix << std::endl; + // std::cout << "targetRowValues before ec elim:\n" << storm::utility::vector::toString(targetRowValues) << std::endl; + // std::cout << "conditionRowValues before ec elim:\n" << storm::utility::vector::toString(conditionRowValues) << std::endl; + // eliminate ECs if present. We already checked that the initial state can not yield observation failure, so it cannot be part of an EC. + // For all remaining ECs, staying in an EC forever is reflected by collecting a value of zero for both, target and condition + storm::storage::BitVector allExceptInit(numSubmatrixRowGroups, true); + allExceptInit.set(initialStateInSubmatrix, false); + eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, + conditionRowValues); + // std::cout << "Submatrix after ec elim:\n" << submatrix << std::endl; + // std::cout << "targetRowValues after ec elim:\n" << storm::utility::vector::toString(targetRowValues) << std::endl; + // std::cout << "conditionRowValues after ec elim:\n" << storm::utility::vector::toString(conditionRowValues) << std::endl; + STORM_PRINT_AND_LOG("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " + << submatrix.getEntryCount() << " transitions.\n"); + } + + SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, + ValueType const& conditionWeight) const { + auto rowValues = createScaledVector(targetWeight, targetRowValues, -conditionWeight, conditionRowValues); + + // Initialize the solution vector. + std::vector x(submatrix.getRowGroupCount(), storm::utility::zero()); + + // Set up the solver. + auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(env, submatrix); + solver->setOptimizationDirection(dir); + solver->setRequirementsChecked(); + solver->setHasUniqueSolution(true); + solver->setHasNoEndComponents(true); + solver->setLowerBound(-storm::utility::one()); + solver->setUpperBound(storm::utility::one()); + + // std::cout << "solving equation system with matrix \n" << submatrix << " and row values \n" << storm::utility::vector::toString(rowValues) << + // std::endl; Solve the corresponding system of equations. + solver->solveEquations(env, x, rowValues); + return x[initialStateInSubmatrix]; + } + + private: + std::vector createScaledVector(ValueType const& w1, std::vector const& v1, ValueType const& w2, + std::vector const& v2) const { + STORM_LOG_ASSERT(v1.size() == v2.size(), "Vector sizes must match"); + std::vector result; + result.reserve(v1.size()); + for (size_t i = 0; i < v1.size(); ++i) { + result.push_back(w1 * v1[i] + w2 * v2[i]); + } + return result; + } + + storm::storage::SparseMatrix submatrix; + storm::storage::BitVector rowsWithSum1; + std::vector targetRowValues; + std::vector conditionRowValues; + uint64_t initialStateInSubmatrix; +}; + +template +SolutionType computeViaBinarySearch(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { + SolutionType const precision = storm::utility::convertNumber(env.solver().minMax().getPrecision()); + bool const relative = env.solver().minMax().getRelativeTerminationCriterion(); + + WeightedDiffComputer wdc(initialState, transitionMatrix, normalForm); + SolutionType lowerBound = storm::utility::zero(); + SolutionType upperBound = storm::utility::one(); + storm::Environment absEnv = env; + absEnv.solver().minMax().setRelativeTerminationCriterion(false); + for (uint64_t iterationCount = 1; true; ++iterationCount) { + SolutionType const middle = (lowerBound + upperBound) / 2; + SolutionType const middleValue = wdc.computeWeightedDiff(env, dir, storm::utility::one(), middle); + if (middleValue >= storm::utility::zero()) { + lowerBound = middle; + } + if (middleValue <= storm::utility::zero()) { + upperBound = middle; + } + SolutionType const boundDiff = upperBound - lowerBound; + STORM_LOG_INFO("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(lowerBound) + << ",\n\t Upper bound: " << storm::utility::convertNumber(upperBound) + << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) + << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "\n\n"); + if (boundDiff <= (relative ? (precision * lowerBound) : precision)) { + break; + } + } + return (lowerBound + upperBound) / 2; } } // namespace internal @@ -244,31 +503,43 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // @see doi.org/10.1007/978-3-642-54862-8_43 STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, "Only one initial state is supported for conditional probabilities"); + STORM_PRINT_AND_LOG("Computing conditional probabilities for a model with " << transitionMatrix.getRowGroupCount() << " states and " + << transitionMatrix.getEntryCount() << " transitions.\n"); storm::utility::Stopwatch sw(true); - auto normalFormData = internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, targetStates, conditionStates); - STORM_PRINT_AND_LOG("Time for obtaining the normal form:" << sw << ".\n"); - - sw.restart(); - // Then, we solve the induced problem using the selected algorithm[p + auto normalFormData = + internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), targetStates, conditionStates); + sw.stop(); + STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); + // Then, we solve the induced problem using the selected algorithm auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); - auto const algString = storm::settings::getModule().getConditionalAlgorithm(); if (normalFormData.terminalStates.get(initialState)) { if (normalFormData.conditionStates.get(initialState)) { initialStateValue = normalFormData.targetValue(initialState); // The value is already known, nothing to do. } else { - STORM_LOG_THROW(!normalFormData.observationFailureStates.get(initialState), storm::exceptions::NotSupportedException, + STORM_LOG_THROW(!normalFormData.universalObservationFailureStates.get(initialState), storm::exceptions::NotSupportedException, "Trying to compute undefined conditional probability: the condition has probability 0 under all policies."); // The last case for a terminal initial state is that it is already target and the condition is reachable with non-zero probability. // In this case, all schedulers induce a conditional probability of 1 (or do not reach the condition, i.e., have undefined value) initialStateValue = storm::utility::one(); } - } else if (algString == "restart" || algString == "default") { - initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + STORM_PRINT_AND_LOG("Initial state is terminal.\n"); } else { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); + STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState), "Initial state must be a maybe state if it is not a terminal state"); + auto const algString = storm::settings::getModule().getConditionalAlgorithm(); + STORM_PRINT_AND_LOG("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << algString + << "'.\n"); + sw.restart(); + if (algString == "restart" || algString == "default") { + initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else if (algString == "binary") { + initialStateValue = internal::computeViaBinarySearch(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); + } + sw.stop(); + STORM_PRINT_AND_LOG("Time for analyzing the normal form: " << sw << ".\n"); } - STORM_PRINT_AND_LOG("Time for analyzing the normal form:" << sw << ".\n"); return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); } From d1629b2f358163247272e2438ef1c4a27c135d5e Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sun, 26 Jan 2025 13:13:58 +0100 Subject: [PATCH 019/102] bisection approach (simple and advanced version) --- .../helper/conditional/ConditionalHelper.cpp | 89 ++++++++++++++----- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 7aedab0352..e44e56bf65 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -12,6 +12,7 @@ #include "storm/storage/MaximalEndComponentDecomposition.h" #include "storm/storage/SparseMatrix.h" #include "storm/transformer/EndComponentEliminator.h" +#include "storm/utility/Extremum.h" #include "storm/utility/Stopwatch.h" #include "storm/utility/graph.h" #include "storm/utility/macros.h" @@ -364,10 +365,13 @@ class WeightedDiffComputer { // Put the row processing into a lambda for avoiding code duplications auto processRow = [&](uint64_t origRowIndex) { - // Find out the target and condition probabilities for this row + // We make two passes. First, we find out the probability to reach an eliminated initial component state + ValueType const eliminatedInitialComponentProbability = transitionMatrix.getConstrainedRowSum(origRowIndex, eliminatedInitialComponentStates); + // Second, we insert the submatrix entries and find out the target and condition probabilities for this row ValueType targetProbability = storm::utility::zero(); ValueType conditionProbability = storm::utility::zero(); bool rowSumIsLess1 = false; + bool initialStateEntryInserted = false; for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { if (normalForm.terminalStates.get(entry.getColumn())) { STORM_LOG_ASSERT(!storm::utility::isZero(entry.getValue()), "Transition probability must be non-zero"); @@ -379,8 +383,19 @@ class WeightedDiffComputer { } else { conditionProbability += scaledTargetValue; // for terminal, non-condition states, the condition value equals the target value } - } else { - matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[entry.getColumn()], entry.getValue()); + } else if (!eliminatedInitialComponentStates.get(entry.getColumn())) { + auto const columnIndex = stateToMatrixIndexMap[entry.getColumn()]; + if (!initialStateEntryInserted && columnIndex >= initialStateInSubmatrix) { + if (columnIndex == initialStateInSubmatrix) { + matrixBuilder.addNextValue(currentRow, initialStateInSubmatrix, eliminatedInitialComponentProbability + entry.getValue()); + } else { + matrixBuilder.addNextValue(currentRow, initialStateInSubmatrix, eliminatedInitialComponentProbability); + matrixBuilder.addNextValue(currentRow, columnIndex, entry.getValue()); + } + initialStateEntryInserted = true; + } else { + matrixBuilder.addNextValue(currentRow, columnIndex, entry.getValue()); + } } } if (rowSumIsLess1) { @@ -421,7 +436,7 @@ class WeightedDiffComputer { SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, ValueType const& conditionWeight) const { - auto rowValues = createScaledVector(targetWeight, targetRowValues, -conditionWeight, conditionRowValues); + auto rowValues = createScaledVector(targetWeight, targetRowValues, conditionWeight, conditionRowValues); // Initialize the solution vector. std::vector x(submatrix.getRowGroupCount(), storm::utility::zero()); @@ -460,36 +475,64 @@ class WeightedDiffComputer { uint64_t initialStateInSubmatrix; }; +enum class BisectionMethodBounds { Simple, Advanced }; template -SolutionType computeViaBinarySearch(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { +SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds boundOption, uint64_t const initialState, + storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, + NormalFormData const& normalForm) { SolutionType const precision = storm::utility::convertNumber(env.solver().minMax().getPrecision()); bool const relative = env.solver().minMax().getRelativeTerminationCriterion(); WeightedDiffComputer wdc(initialState, transitionMatrix, normalForm); - SolutionType lowerBound = storm::utility::zero(); - SolutionType upperBound = storm::utility::one(); + SolutionType pMin{storm::utility::zero()}; + SolutionType pMax{storm::utility::one()}; + if (boundOption == BisectionMethodBounds::Advanced) { + pMin = wdc.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); + pMax = wdc.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); + STORM_LOG_INFO("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) + << ",\n\t Upper bound: " << storm::utility::convertNumber(pMax) << "\n\n"); + } + storm::utility::Extremum lowerBound = storm::utility::zero(); + storm::utility::Extremum upperBound = storm::utility::one(); storm::Environment absEnv = env; absEnv.solver().minMax().setRelativeTerminationCriterion(false); for (uint64_t iterationCount = 1; true; ++iterationCount) { - SolutionType const middle = (lowerBound + upperBound) / 2; - SolutionType const middleValue = wdc.computeWeightedDiff(env, dir, storm::utility::one(), middle); - if (middleValue >= storm::utility::zero()) { - lowerBound = middle; - } - if (middleValue <= storm::utility::zero()) { - upperBound = middle; + SolutionType const middle = (*lowerBound + *upperBound) / 2; + SolutionType const middleValue = wdc.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + if (boundOption == BisectionMethodBounds::Simple) { + if (middleValue >= storm::utility::zero()) { + lowerBound &= middle; + } + if (middleValue <= storm::utility::zero()) { + upperBound &= middle; + } + } else { + STORM_LOG_ASSERT(boundOption == BisectionMethodBounds::Advanced, "Unknown bisection method bounds"); + if (middleValue >= storm::utility::zero()) { + lowerBound &= middle + (middleValue / pMax); + upperBound &= middle + (middleValue / pMin); + } + if (middleValue <= storm::utility::zero()) { + lowerBound &= middle + (middleValue / pMin); + upperBound &= middle + (middleValue / pMax); + } } - SolutionType const boundDiff = upperBound - lowerBound; - STORM_LOG_INFO("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(lowerBound) - << ",\n\t Upper bound: " << storm::utility::convertNumber(upperBound) + SolutionType const boundDiff = *upperBound - *lowerBound; + STORM_LOG_INFO("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) + << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "\n\n"); - if (boundDiff <= (relative ? (precision * lowerBound) : precision)) { + if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { + STORM_PRINT_AND_LOG("Bisection method converged after " << iterationCount << " iterations.\n"); + STORM_PRINT_AND_LOG("Difference is " << std::setprecision(std::numeric_limits::digits10) << storm::utility::convertNumber(boundDiff) + << ".\n"); + if (std::is_same_v && storm::utility::isZero(boundDiff)) { + STORM_PRINT_AND_LOG("Result is exact."); + } break; } } - return (lowerBound + upperBound) / 2; + return (*lowerBound + *upperBound) / 2; } } // namespace internal @@ -532,8 +575,10 @@ std::unique_ptr computeConditionalProbabilities(Environment const& sw.restart(); if (algString == "restart" || algString == "default") { initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); - } else if (algString == "binary") { - initialStateValue = internal::computeViaBinarySearch(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else if (algString == "bisection" || algString == "bisection-advanced") { + auto const boundOption = (algString == "bisection" ? internal::BisectionMethodBounds::Simple : internal::BisectionMethodBounds::Advanced); + initialStateValue = + internal::computeViaBisection(env, boundOption, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); } else { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); } From 8bf8b7c37f21686c35101e41726ba9caa8c87bf2 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Mon, 27 Jan 2025 07:45:52 +0100 Subject: [PATCH 020/102] policy iteration --- .../helper/conditional/ConditionalHelper.cpp | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index e44e56bf65..57de83d07d 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -456,6 +456,68 @@ class WeightedDiffComputer { return x[initialStateInSubmatrix]; } + auto getInternalInitialState() const { + return initialStateInSubmatrix; + } + + void evaluateScheduler(storm::Environment const& env, std::vector& scheduler, std::vector& targetResults, + std::vector& conditionResults) const { + if (scheduler.empty()) { + scheduler.resize(submatrix.getRowGroupCount(), 0); + } + if (targetResults.empty()) { + targetResults.resize(submatrix.getRowGroupCount(), storm::utility::zero()); + } + if (conditionResults.empty()) { + conditionResults.resize(submatrix.getRowGroupCount(), storm::utility::zero()); + } + // apply the scheduler + storm::solver::GeneralLinearEquationSolverFactory factory; + bool const convertToEquationSystem = factory.getEquationProblemFormat(env) == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; + auto scheduledMatrix = submatrix.selectRowsFromRowGroups(scheduler, convertToEquationSystem); + if (convertToEquationSystem) { + scheduledMatrix.convertToEquationSystem(); + } + auto solver = factory.create(env, std::move(scheduledMatrix)); + solver->setBounds(storm::utility::zero(), storm::utility::one()); + solver->setCachingEnabled(true); + + std::vector subB(submatrix.getRowGroupCount()); + storm::utility::vector::selectVectorValues(subB, scheduler, submatrix.getRowGroupIndices(), targetRowValues); + solver->solveEquations(env, targetResults, subB); + + storm::utility::vector::selectVectorValues(subB, scheduler, submatrix.getRowGroupIndices(), conditionRowValues); + solver->solveEquations(env, conditionResults, subB); + } + + template + bool improveScheduler(std::vector& scheduler, ValueType const& lambda, std::vector const& targetResults, + std::vector const& conditionResults) { + bool improved = false; + for (uint64_t rowGroupIndex = 0; rowGroupIndex < scheduler.size(); ++rowGroupIndex) { + storm::utility::Extremum groupValue; + uint64_t optimalRowIndex{0}; + ValueType scheduledValue; + for (auto rowIndex : submatrix.getRowGroupIndices(rowGroupIndex)) { + ValueType rowValue = targetRowValues[rowIndex] - lambda * conditionRowValues[rowIndex]; + for (auto const& entry : submatrix.getRow(rowIndex)) { + rowValue += entry.getValue() * (targetResults[entry.getColumn()] - lambda * conditionResults[entry.getColumn()]); + } + if (rowIndex == scheduler[rowGroupIndex] + submatrix.getRowGroupIndices()[rowGroupIndex]) { + scheduledValue = rowValue; + } + if (groupValue &= rowValue) { + optimalRowIndex = rowIndex; + } + } + if (scheduledValue != *groupValue) { + scheduler[rowGroupIndex] = optimalRowIndex - submatrix.getRowGroupIndices()[rowGroupIndex]; + improved = true; + } + } + return improved; + } + private: std::vector createScaledVector(ValueType const& w1, std::vector const& v1, ValueType const& w2, std::vector const& v2) const { @@ -535,6 +597,33 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b return (*lowerBound + *upperBound) / 2; } +template +SolutionType computeViaPolicyIteration(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { + WeightedDiffComputer wdc(initialState, transitionMatrix, normalForm); + + std::vector scheduler; + std::vector targetResults, conditionResults; + for (uint64_t iterationCount = 1; true; ++iterationCount) { + wdc.evaluateScheduler(env, scheduler, targetResults, conditionResults); + STORM_LOG_ASSERT(targetResults[wdc.getInternalInitialState()] <= conditionResults[wdc.getInternalInitialState()], + "Target value must be less or equal than condition value"); // todo: floats?? + ValueType const lambda = storm::utility::isZero(conditionResults[wdc.getInternalInitialState()]) + ? storm::utility::zero() + : ValueType(targetResults[wdc.getInternalInitialState()] / conditionResults[wdc.getInternalInitialState()]); + bool schedulerChanged{false}; + if (storm::solver::minimize(dir)) { + schedulerChanged = wdc.template improveScheduler(scheduler, lambda, targetResults, conditionResults); + } else { + schedulerChanged = wdc.template improveScheduler(scheduler, lambda, targetResults, conditionResults); + } + if (!schedulerChanged) { + STORM_PRINT_AND_LOG("Policy iteration converged after " << iterationCount << " iterations.\n"); + return lambda; + } + } +} + } // namespace internal template @@ -579,6 +668,8 @@ std::unique_ptr computeConditionalProbabilities(Environment const& auto const boundOption = (algString == "bisection" ? internal::BisectionMethodBounds::Simple : internal::BisectionMethodBounds::Advanced); initialStateValue = internal::computeViaBisection(env, boundOption, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); + } else if (algString == "pi") { + initialStateValue = internal::computeViaPolicyIteration(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); } else { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); } From bc2d82d5688081348528ee20207c3005847977b5 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 25 Apr 2025 10:48:54 +0200 Subject: [PATCH 021/102] fix bug in unfolder --- Dockerfile | 18 +++++++++--------- .../transformer/ObservationTraceUnfolder.cpp | 12 ++++++++++-- .../transformer/ObservationTraceUnfolder.h | 2 +- version.cmake | 2 +- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index b08afb16c3..b8879051cb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ MAINTAINER Matthias Volk # CMake build type ARG build_type=Release # Specify number of threads to use for parallel compilation -ARG no_threads=1 +ARG no_threads=24 # Specify Storm configuration (ON/OFF) ARG gurobi_support="ON" @@ -46,14 +46,14 @@ WORKDIR /opt/storm/build # Configure Storm RUN cmake .. -DCMAKE_BUILD_TYPE=$build_type \ - -DSTORM_PORTABLE=ON \ - -DSTORM_USE_GUROBI=$gurobi_support \ - -DSTORM_USE_SOPLEX=$soplex_support \ - -DSTORM_USE_SPOT_SYSTEM=$spot_support \ - -DSTORM_DEVELOPER=$developer \ - -DSTORM_USE_CLN_EA=$cln_exact \ - -DSTORM_USE_CLN_RF=$cln_ratfunc \ - $cmake_args + -DSTORM_PORTABLE=ON \ + -DSTORM_USE_GUROBI=$gurobi_support \ + -DSTORM_USE_SOPLEX=$soplex_support \ + -DSTORM_USE_SPOT_SYSTEM=$spot_support \ + -DSTORM_DEVELOPER=$developer \ + -DSTORM_USE_CLN_EA=$cln_exact \ + -DSTORM_USE_CLN_RF=$cln_ratfunc \ + $cmake_args # Build external dependencies of Storm RUN make resources -j $no_threads diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index 8ee227c5e4..3235a4815b 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -1,9 +1,12 @@ #include "storm-pomdp/transformer/ObservationTraceUnfolder.h" +#include #include "storm/adapters/RationalFunctionAdapter.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/exceptions/InvalidArgumentException.h" #include "storm/storage/expressions/ExpressionManager.h" #include "storm/utility/ConstantsComparator.h" +#include "storm/utility/macros.h" #undef _VERBOSE_OBSERVATION_UNFOLDING @@ -92,7 +95,8 @@ std::shared_ptr> ObservationTraceUnfolder< #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << "\tconsider new state " << unfoldedToOldEntry.first << '\n'; #endif - assert(step == 0 || newRowCount == transitionMatrixBuilder.getLastRow() + 1); + STORM_LOG_ASSERT(step == 0 || newRowCount == transitionMatrixBuilder.getLastRow() + 1, + "step " << step << " newRowCount " << newRowCount << " lastRow " << transitionMatrixBuilder.getLastRow()); svbuilder.addState(unfoldedToOldEntry.first, {}, {static_cast(unfoldedToOldEntry.second), static_cast(step)}); uint64_t oldRowIndexStart = model.getNondeterministicChoiceIndices()[unfoldedToOldEntry.second]; uint64_t oldRowIndexEnd = model.getNondeterministicChoiceIndices()[unfoldedToOldEntry.second + 1]; @@ -108,6 +112,10 @@ std::shared_ptr> ObservationTraceUnfolder< for (auto const& oldRowEntry : model.getTransitionMatrix().getRow(oldRowIndex)) { if (model.getObservation(oldRowEntry.getColumn()) != observations[step + 1]) { resetProb += oldRowEntry.getValue(); + if constexpr (std::is_same_v) { + resetProb.setUpper(std::min(resetProb.upper(), 1.0)); + resetProb.setLower(std::max(resetProb.lower(), 0.0)); + } } } #ifdef _VERBOSE_OBSERVATION_UNFOLDING @@ -184,7 +192,7 @@ std::shared_ptr> ObservationTraceUnfolder< storm::storage::sparse::ModelComponents components; components.transitionMatrix = transitionMatrixBuilder.build(); #ifdef _VERBOSE_OBSERVATION_UNFOLDING - std::cout << components.transitionMatrix << '\n'; + // std::cout << components.transitionMatrix << '\n'; #endif STORM_LOG_ASSERT(components.transitionMatrix.getRowGroupCount() == targetState + 1, "Expect row group count (" << components.transitionMatrix.getRowGroupCount() << ") one more as target state index " << targetState << ")"); diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h index c5b2c6625b..ea2789b9ca 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h @@ -45,7 +45,7 @@ class ObservationTraceUnfolder { bool isRejectionSamplingSet() const; private: - storm::models::sparse::Pomdp const& model; + storm::models::sparse::Pomdp model; std::vector risk; // TODO reconsider holding this as a reference, but there were some strange bugs std::shared_ptr& exprManager; std::vector statesPerObservation; diff --git a/version.cmake b/version.cmake index 214c98d784..71b819bde2 100644 --- a/version.cmake +++ b/version.cmake @@ -1,4 +1,4 @@ set(STORM_VERSION_MAJOR 1) set(STORM_VERSION_MINOR 9) -set(STORM_VERSION_PATCH 0) +set(STORM_VERSION_PATCH 1) From 1dcf99195824c97e9e1863f86ca09f672575e7ca Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 20 May 2025 17:59:49 +0200 Subject: [PATCH 022/102] wip --- .../transformer/ObservationTraceUnfolder.cpp | 4 + src/storm/adapters/RationalNumberForward.h | 2 + .../modelchecker/AbstractModelChecker.cpp | 5 + src/storm/modelchecker/AbstractModelChecker.h | 18 ++- .../hints/ExplicitModelCheckerHint.cpp | 1 + .../modelchecker/hints/ModelCheckerHint.cpp | 2 + .../prctl/SparseMdpPrctlModelChecker.cpp | 19 +-- .../prctl/SparseMdpPrctlModelChecker.h | 17 ++- .../SparseMdpEndComponentInformation.cpp | 11 +- .../prctl/helper/SparseMdpPrctlHelper.cpp | 130 ++++++++++++----- .../prctl/helper/SparseMdpPrctlHelper.h | 6 + .../SparsePropositionalModelChecker.cpp | 5 + .../SparsePropositionalModelChecker.h | 17 ++- src/storm/models/sparse/Ctmc.cpp | 2 + .../models/sparse/DeterministicModel.cpp | 2 + src/storm/models/sparse/Dtmc.cpp | 2 + src/storm/models/sparse/MarkovAutomaton.cpp | 2 + src/storm/models/sparse/Mdp.cpp | 2 + src/storm/models/sparse/Model.cpp | 2 + .../models/sparse/NondeterministicModel.cpp | 2 + src/storm/models/sparse/Pomdp.cpp | 2 + src/storm/models/sparse/Smg.cpp | 2 + .../models/sparse/StandardRewardModel.cpp | 41 ++++++ .../models/sparse/StochasticTwoPlayerGame.cpp | 2 + .../IterativeMinMaxLinearEquationSolver.cpp | 30 ++-- src/storm/solver/LinearEquationSolver.cpp | 2 +- .../solver/MinMaxLinearEquationSolver.cpp | 10 +- src/storm/solver/SolveGoal.cpp | 1 + .../StandardMinMaxLinearEquationSolver.cpp | 1 + .../solver/helper/SchedulerTrackingHelper.cpp | 2 + .../solver/helper/ValueIterationHelper.cpp | 2 + .../solver/helper/ValueIterationOperator.cpp | 2 + .../solver/helper/ValueIterationOperator.h | 8 +- src/storm/storage/Distribution.cpp | 5 + .../MaximalEndComponentDecomposition.cpp | 4 + src/storm/storage/Scheduler.cpp | 1 + src/storm/storage/SchedulerChoice.cpp | 2 + src/storm/storage/SparseMatrix.cpp | 14 ++ ...tronglyConnectedComponentDecomposition.cpp | 1 + .../MemoryStructureBuilder.cpp | 2 + .../SparseModelMemoryProduct.cpp | 2 + src/storm/transformer/AddUncertainty.cpp | 1 + src/storm/transformer/SubsystemBuilder.cpp | 8 ++ src/storm/utility/ConstantsComparator.cpp | 1 + src/storm/utility/builder.cpp | 5 + src/storm/utility/constants.cpp | 53 +++++++ src/storm/utility/graph.cpp | 135 ++++++++++++++++++ 47 files changed, 523 insertions(+), 67 deletions(-) diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index 3235a4815b..b163884e9c 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -115,6 +115,9 @@ std::shared_ptr> ObservationTraceUnfolder< if constexpr (std::is_same_v) { resetProb.setUpper(std::min(resetProb.upper(), 1.0)); resetProb.setLower(std::max(resetProb.lower(), 0.0)); + } else if constexpr (std::is_same_v) { + resetProb.setUpper(std::min(resetProb.upper(), utility::one())); + resetProb.setLower(std::max(resetProb.lower(), utility::zero())); } } } @@ -230,6 +233,7 @@ bool ObservationTraceUnfolder::isRejectionSamplingSet() const { template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; +template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; template class ObservationTraceUnfolder; } // namespace pomdp diff --git a/src/storm/adapters/RationalNumberForward.h b/src/storm/adapters/RationalNumberForward.h index 8bb71b3c2b..d2c040dc70 100644 --- a/src/storm/adapters/RationalNumberForward.h +++ b/src/storm/adapters/RationalNumberForward.h @@ -41,4 +41,6 @@ typedef GmpRationalNumber RationalNumber; #else #error GMP is to be used, but is not available. #endif + +typedef carl::Interval RationalInterval; } // namespace storm diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index 5b4d3f92e9..a9c3cbf1cc 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -455,6 +455,9 @@ template class AbstractModelChecker>; template class AbstractModelChecker>>; template class AbstractModelChecker>>; +template class AbstractModelChecker>>; +template class AbstractModelChecker>>; + template class AbstractModelChecker>; template class AbstractModelChecker>; template class AbstractModelChecker>; @@ -472,6 +475,8 @@ template class AbstractModelChecker>; +template class AbstractModelChecker>; + // DD template class AbstractModelChecker>; template class AbstractModelChecker>; diff --git a/src/storm/modelchecker/AbstractModelChecker.h b/src/storm/modelchecker/AbstractModelChecker.h index 45ba3fcac7..31d1b4673f 100644 --- a/src/storm/modelchecker/AbstractModelChecker.h +++ b/src/storm/modelchecker/AbstractModelChecker.h @@ -15,13 +15,29 @@ class CheckResult; template class AbstractModelChecker { + private: + template + struct GetSolutionType { + using type = T; + }; + + template<> + struct GetSolutionType { + using type = double; + }; + + template<> + struct GetSolutionType { + using type = storm::RationalNumber; + }; + public: virtual ~AbstractModelChecker() { // Intentionally left empty. } typedef typename ModelType::ValueType ValueType; - using SolutionType = typename std::conditional, double, ValueType>::type; + using SolutionType = typename GetSolutionType::type; /*! * Returns the name of the model checker class (e.g., for display in error messages). diff --git a/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp b/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp index 131cbbb083..b932f471ba 100644 --- a/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp +++ b/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp @@ -121,6 +121,7 @@ template class ExplicitModelCheckerHint; template class ExplicitModelCheckerHint; template class ExplicitModelCheckerHint; template class ExplicitModelCheckerHint; +template class ExplicitModelCheckerHint; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/hints/ModelCheckerHint.cpp b/src/storm/modelchecker/hints/ModelCheckerHint.cpp index 0a5fbefcfa..3a181d4d66 100644 --- a/src/storm/modelchecker/hints/ModelCheckerHint.cpp +++ b/src/storm/modelchecker/hints/ModelCheckerHint.cpp @@ -31,6 +31,8 @@ template ExplicitModelCheckerHint const& ModelCheckerHi template ExplicitModelCheckerHint& ModelCheckerHint::asExplicitModelCheckerHint(); template ExplicitModelCheckerHint const& ModelCheckerHint::asExplicitModelCheckerHint() const; template ExplicitModelCheckerHint& ModelCheckerHint::asExplicitModelCheckerHint(); +template ExplicitModelCheckerHint const& ModelCheckerHint::asExplicitModelCheckerHint() const; +template ExplicitModelCheckerHint& ModelCheckerHint::asExplicitModelCheckerHint(); } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index a82243a142..c06a027a4f 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -36,7 +36,7 @@ template bool SparseMdpPrctlModelChecker::canHandleStatic(CheckTask const& checkTask, bool* requiresSingleInitialState) { storm::logic::Formula const& formula = checkTask.getFormula(); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { if (formula.isInFragment(storm::logic::propositional())) { return true; } @@ -108,7 +108,7 @@ bool SparseMdpPrctlModelChecker::canHandle(CheckTask std::unique_ptr SparseMdpPrctlModelChecker::computeBoundedUntilProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented bounded until with intervals"); return nullptr; } else { @@ -203,7 +203,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeHOAPathProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented automata-props with intervals"); } else { storm::logic::HOAPathFormula const& pathFormula = checkTask.getFormula(); @@ -230,7 +230,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLTLProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented LTL with intervals"); } else { storm::logic::PathFormula const& pathFormula = checkTask.getFormula(); @@ -386,7 +386,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented LRA probabilities with intervals"); } else { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); @@ -411,7 +411,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageRewards( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lra with intervals"); } else { STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, @@ -432,7 +432,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::checkMultiObjectiveFormula( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented multi-objective with intervals"); } else { return multiobjective::performMultiObjectiveModelChecking(env, this->getModel(), checkTask.getFormula()); @@ -442,7 +442,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template std::unique_ptr SparseMdpPrctlModelChecker::checkLexObjectiveFormula( const Environment& env, const CheckTask& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { @@ -457,7 +457,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template std::unique_ptr SparseMdpPrctlModelChecker::checkQuantileFormula( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented quantile formulas with intervals"); } else { STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, @@ -480,5 +480,6 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template class SparseMdpPrctlModelChecker>; template class SparseMdpPrctlModelChecker>; template class SparseMdpPrctlModelChecker>; +template class SparseMdpPrctlModelChecker>; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h index 4164ca67a2..48e9134f3b 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h @@ -11,10 +11,25 @@ class Environment; namespace modelchecker { template class SparseMdpPrctlModelChecker : public SparsePropositionalModelChecker { + private: + template + struct GetSolutionType { + using type = T; + }; + + template<> + struct GetSolutionType { + using type = double; + }; + + template<> + struct GetSolutionType { + using type = storm::RationalNumber; + }; public: typedef typename SparseMdpModelType::ValueType ValueType; typedef typename SparseMdpModelType::RewardModelType RewardModelType; - using SolutionType = typename std::conditional, double, ValueType>::type; + using SolutionType = typename GetSolutionType::type; explicit SparseMdpPrctlModelChecker(SparseMdpModelType const& model); diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp index e4f9a7be27..f4c3b2f24c 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp @@ -106,7 +106,7 @@ SparseMdpEndComponentInformation SparseMdpEndComponentInformation* columnSumVector, std::vector* summandResultVector, bool gatherExitChoices) { SparseMdpEndComponentInformation result(endComponentDecomposition, maybeStates); // TODO: Just like SparseMdpPrctlHelper::computeFixedPointSystemUntilProbabilities, this method must be adapted for intervals. - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support the elimination of end components and the creation of an adequate equation system with interval models."); } @@ -248,7 +248,7 @@ SparseMdpEndComponentInformation SparseMdpEndComponentInformation& submatrix, std::vector& subvector, bool gatherExitChoices) { SparseMdpEndComponentInformation result(endComponentDecomposition, maybeStates); // TODO: Just like SparseMdpPrctlHelper::computeFixedPointSystemUntilProbabilities, this method must be adapted for intervals. - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support the elimination of end components and the creation of an adequate equation system with interval models."); } @@ -422,6 +422,7 @@ void SparseMdpEndComponentInformation::setScheduler(storm::storage::S template class SparseMdpEndComponentInformation; template class SparseMdpEndComponentInformation; template class SparseMdpEndComponentInformation; +template class SparseMdpEndComponentInformation; template void SparseMdpEndComponentInformation::setScheduler(storm::storage::Scheduler& scheduler, storm::storage::BitVector const& maybeStates, storm::storage::SparseMatrix const& transitionMatrix, @@ -439,6 +440,12 @@ template void SparseMdpEndComponentInformation::setScheduler(st storm::storage::SparseMatrix const& backwardTransitions, std::vector const& fromResult); +template void SparseMdpEndComponentInformation::setScheduler(storm::storage::Scheduler& scheduler, + storm::storage::BitVector const& maybeStates, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + std::vector const& fromResult); + // template class SparseMdpEndComponentInformation; } // namespace helper diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 064a9cc785..e6bde0c90d 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -58,7 +58,7 @@ template std::map SparseMdpPrctlHelper::computeRewardBoundedValues( Environment const& env, OptimizationDirection dir, rewardbounded::MultiDimensionalRewardUnfolding& rewardUnfolding, storm::storage::BitVector const& initialStates) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reward bounded values with interval models."); } else { storm::utility::Stopwatch swAll(true), swBuild, swCheck; @@ -148,7 +148,7 @@ template std::vector SparseMdpPrctlHelper::computeNextProbabilities( Environment const& env, OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with reward models."); } else { // Create the vector with which to multiply and initialize it correctly. @@ -620,7 +620,7 @@ void computeFixedPointSystemUntilProbabilities(storm::solver::SolveGoal const& transitionMatrix, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix& submatrix, std::vector& b) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { // For non-interval based models, we can eliminate the rows and columns from the original transition probability matrix for states // whose probabilities are already known... However, there is information in the transition to those states. // Thus, we cannot eliminate them all. @@ -765,7 +765,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support this end component with interval models."); } else { ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); @@ -776,7 +776,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper) { + if constexpr (!std::is_same_v && !std::is_same_v) { // For non-interval models, we only operated on the maybe states, and we must recover the qualitative values for the other state. storm::utility::vector::setVectorValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); } else { @@ -841,7 +841,7 @@ template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support instantenous rewards with interval models."); } else { // Only compute the result if the model has a state-based reward this->getModel(). @@ -862,7 +862,7 @@ template std::vector SparseMdpPrctlHelper::computeCumulativeRewards( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support cumulative rewards with interval models."); } else { // Only compute the result if the model has at least one reward this->getModel(). @@ -1019,27 +1019,65 @@ std::vector SparseMdpPrctlHelper::compute bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative) { // Only compute the result if the reward model is not empty. STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); - return computeReachabilityRewardsHelper( - env, std::move(goal), transitionMatrix, backwardTransitions, - [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { - std::vector result; - result.reserve(rowCount); - std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); - for (auto const& interval : subIntervalVector) { - result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); - } - return result; - }, - targetStates, qualitative, false, - [&]() { - return intervalRewardModel.getStatesWithFilter( - transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); - }, - [&]() { - return intervalRewardModel.getChoicesWithFilter( - transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); - }) - .values; + if constexpr (std::is_same_v) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support rational interval rewards with double interval models."); + } else { + return computeReachabilityRewardsHelper( + env, std::move(goal), transitionMatrix, backwardTransitions, + [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + std::vector result; + result.reserve(rowCount); + std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); + for (auto const& interval : subIntervalVector) { + result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); + } + return result; + }, + targetStates, qualitative, false, + [&]() { + return intervalRewardModel.getStatesWithFilter( + transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }, + [&]() { + return intervalRewardModel.getChoicesWithFilter( + transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }) + .values; + } +} + +template +std::vector SparseMdpPrctlHelper::computeReachabilityRewards( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, + bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative) { + // Only compute the result if the reward model is not empty. + STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); + if constexpr (std::is_same_v) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support interval rewards with rational interval models."); + } else { + return computeReachabilityRewardsHelper( + env, std::move(goal), transitionMatrix, backwardTransitions, + [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + std::vector result; + result.reserve(rowCount); + std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); + for (auto const& interval : subIntervalVector) { + result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); + } + return result; + }, + targetStates, qualitative, false, + [&]() { + return intervalRewardModel.getStatesWithFilter( + transitionMatrix, [&](storm::RationalInterval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }, + [&]() { + return intervalRewardModel.getChoicesWithFilter( + transitionMatrix, [&](storm::RationalInterval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }) + .values; + } } template<> @@ -1049,6 +1087,14 @@ std::vector SparseMdpPrctlHelper:: storm::storage::BitVector const&, bool) { STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type."); } + +template<> +std::vector SparseMdpPrctlHelper::computeReachabilityRewards( + Environment const& env, storm::solver::SolveGoal&&, storm::storage::SparseMatrix const&, + storm::storage::SparseMatrix const&, storm::models::sparse::StandardRewardModel const&, bool, + storm::storage::BitVector const&, bool) { + STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type."); +} #endif struct QualitativeStateSetsReachabilityRewards { @@ -1291,7 +1337,7 @@ template void computeUpperRewardBounds(SparseMdpHintType& hintInformation, storm::OptimizationDirection const& direction, storm::storage::SparseMatrix const& submatrix, std::vector const& choiceRewards, std::vector const& oneStepTargetProbabilities) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing upper reward bounds with interval models."); } else { // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17). @@ -1330,7 +1376,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper> scheduler; if (produceScheduler) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support producing schedulers in this function with interval models."); } else { scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); @@ -1375,7 +1421,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper> ecInformation; if (hintInformation.getEliminateEndComponents()) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models."); } else { ecInformation = computeFixedPointSystemReachabilityRewardsEliminateEndComponents( @@ -1400,7 +1446,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models."); } else { ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); @@ -1431,7 +1477,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelperisDeterministicScheduler(), "Expected a deterministic scheduler"); STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler"); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { return MDPSparseModelCheckingHelperReturnType(std::move(result)); } else { return MDPSparseModelCheckingHelperReturnType(std::move(result), std::move(scheduler)); @@ -1443,7 +1489,7 @@ std::unique_ptr SparseMdpPrctlHelper::comp Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional probabilities with interval models."); } else { std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); @@ -1665,6 +1711,22 @@ template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint); +template class SparseMdpPrctlHelper; +template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepCount); +template std::vector SparseMdpPrctlHelper::computeCumulativeRewards( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepBound); +template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, + storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint); +template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeTotalRewards( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, + bool qualitative, bool produceScheduler, ModelCheckerHint const& hint); + } // namespace helper } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h index 5510b92c13..a9067aba6a 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h @@ -92,6 +92,12 @@ class SparseMdpPrctlHelper { storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative); + static std::vector computeReachabilityRewards(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& intervalRewardModel, + bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative); + static std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp index 094a2332cf..25e2cc0cbc 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -68,6 +68,9 @@ template class SparsePropositionalModelChecker>>; template class SparsePropositionalModelChecker>>; +template class SparsePropositionalModelChecker>>; +template class SparsePropositionalModelChecker>>; + template class SparsePropositionalModelChecker>; template class SparsePropositionalModelChecker>; template class SparsePropositionalModelChecker>; @@ -84,6 +87,8 @@ template class SparsePropositionalModelChecker>; template class SparsePropositionalModelChecker>; + +template class SparsePropositionalModelChecker>; #endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h index 52a6c3c137..a1a63024d3 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h @@ -8,10 +8,25 @@ namespace modelchecker { template class SparsePropositionalModelChecker : public AbstractModelChecker { + private: + template + struct GetSolutionType { + using type = T; + }; + + template<> + struct GetSolutionType { + using type = double; + }; + + template<> + struct GetSolutionType { + using type = storm::RationalNumber; + }; public: typedef typename SparseModelType::ValueType ValueType; typedef typename SparseModelType::RewardModelType RewardModelType; - using SolutionType = typename std::conditional, double, ValueType>::type; + using SolutionType = typename GetSolutionType::type; explicit SparsePropositionalModelChecker(SparseModelType const& model); diff --git a/src/storm/models/sparse/Ctmc.cpp b/src/storm/models/sparse/Ctmc.cpp index 28aaaeaaa5..ac320a8ffe 100644 --- a/src/storm/models/sparse/Ctmc.cpp +++ b/src/storm/models/sparse/Ctmc.cpp @@ -96,8 +96,10 @@ template class Ctmc; template class Ctmc; template class Ctmc>; +template class Ctmc>; template class Ctmc; template class Ctmc; +template class Ctmc; #endif } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/DeterministicModel.cpp b/src/storm/models/sparse/DeterministicModel.cpp index 981716028c..e34ebd74ed 100644 --- a/src/storm/models/sparse/DeterministicModel.cpp +++ b/src/storm/models/sparse/DeterministicModel.cpp @@ -65,8 +65,10 @@ template class DeterministicModel; template class DeterministicModel; template class DeterministicModel>; +template class DeterministicModel>; template class DeterministicModel; template class DeterministicModel; +template class DeterministicModel; #endif } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Dtmc.cpp b/src/storm/models/sparse/Dtmc.cpp index a477daf6bb..6c029629b9 100644 --- a/src/storm/models/sparse/Dtmc.cpp +++ b/src/storm/models/sparse/Dtmc.cpp @@ -50,8 +50,10 @@ template class Dtmc; template class Dtmc; template class Dtmc>; +template class Dtmc>; template class Dtmc; template class Dtmc; +template class Dtmc; #endif } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/MarkovAutomaton.cpp b/src/storm/models/sparse/MarkovAutomaton.cpp index 279671ac79..aa1fe31184 100644 --- a/src/storm/models/sparse/MarkovAutomaton.cpp +++ b/src/storm/models/sparse/MarkovAutomaton.cpp @@ -263,9 +263,11 @@ template class MarkovAutomaton; template class MarkovAutomaton; template class MarkovAutomaton>; +template class MarkovAutomaton>; template class MarkovAutomaton; template class MarkovAutomaton; +template class MarkovAutomaton; #endif } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Mdp.cpp b/src/storm/models/sparse/Mdp.cpp index 4d8b3b83d0..91f98e9d60 100644 --- a/src/storm/models/sparse/Mdp.cpp +++ b/src/storm/models/sparse/Mdp.cpp @@ -46,8 +46,10 @@ template class Mdp; template class Mdp; template class Mdp>; +template class Mdp>; template class Mdp; template class Mdp; +template class Mdp; } // namespace sparse } // namespace models } // namespace storm diff --git a/src/storm/models/sparse/Model.cpp b/src/storm/models/sparse/Model.cpp index c89e4ba8e3..09b41089cb 100644 --- a/src/storm/models/sparse/Model.cpp +++ b/src/storm/models/sparse/Model.cpp @@ -736,9 +736,11 @@ std::set getAllParameters(Model; template class Model; +template class Model; template class Model; template class Model>; +template class Model>; template class Model; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/NondeterministicModel.cpp b/src/storm/models/sparse/NondeterministicModel.cpp index 83b954a2f1..bb8ad4128a 100644 --- a/src/storm/models/sparse/NondeterministicModel.cpp +++ b/src/storm/models/sparse/NondeterministicModel.cpp @@ -192,8 +192,10 @@ template class NondeterministicModel; #ifdef STORM_HAVE_CARL template class NondeterministicModel; template class NondeterministicModel>; +template class NondeterministicModel>; template class NondeterministicModel; template class NondeterministicModel; +template class NondeterministicModel; #endif } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Pomdp.cpp b/src/storm/models/sparse/Pomdp.cpp index 219d007edc..afe69f0d7b 100644 --- a/src/storm/models/sparse/Pomdp.cpp +++ b/src/storm/models/sparse/Pomdp.cpp @@ -154,8 +154,10 @@ std::size_t Pomdp::hash() const { template class Pomdp; template class Pomdp; template class Pomdp>; +template class Pomdp>; template class Pomdp; template class Pomdp; +template class Pomdp; } // namespace sparse } // namespace models } // namespace storm diff --git a/src/storm/models/sparse/Smg.cpp b/src/storm/models/sparse/Smg.cpp index cff8895756..f3f64d7e47 100644 --- a/src/storm/models/sparse/Smg.cpp +++ b/src/storm/models/sparse/Smg.cpp @@ -82,8 +82,10 @@ template class Smg; template class Smg; template class Smg>; +template class Smg>; template class Smg; template class Smg; +template class Smg; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/StandardRewardModel.cpp b/src/storm/models/sparse/StandardRewardModel.cpp index 3058778ef8..6c29ab747b 100644 --- a/src/storm/models/sparse/StandardRewardModel.cpp +++ b/src/storm/models/sparse/StandardRewardModel.cpp @@ -629,6 +629,47 @@ template storm::storage::BitVector StandardRewardModel::getChoi storm::storage::SparseMatrix const& transitionMatrix) const; template class StandardRewardModel; template std::ostream& operator<< (std::ostream& out, StandardRewardModel const& rewardModel); + +template std::vector StandardRewardModel::getTotalRewardVector(uint_fast64_t numberOfRows, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::BitVector const& filter) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix) const; +template std::vector StandardRewardModel::getTotalRewardVector(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& weights) const; +template std::vector StandardRewardModel::getTotalRewardVector( + uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& filter) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& weights) const; +template std::vector StandardRewardModel::getTotalActionRewardVector( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& stateRewardWeights) const; +template storm::storage::BitVector StandardRewardModel::getStatesWithFilter(storm::storage::SparseMatrix const& transitionMatrix, + std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getStatesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getChoicesWithFilter(storm::storage::SparseMatrix const& transitionMatrix, + std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getChoicesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; +template void StandardRewardModel::setStateActionReward(uint_fast64_t choiceIndex, storm::RationalNumber const& newValue); +template void StandardRewardModel::setStateActionReward(uint_fast64_t choiceIndex, storm::RationalInterval const& newValue); +template void StandardRewardModel::setStateReward(uint_fast64_t state, storm::RationalNumber const& newValue); +template void StandardRewardModel::setStateReward(uint_fast64_t state, storm::RationalInterval const& newValue); +template void StandardRewardModel::clearRewardAtState(uint_fast64_t state, storm::storage::SparseMatrix const& transitionMatrix); +template void StandardRewardModel::clearRewardAtState(uint_fast64_t state, + storm::storage::SparseMatrix const& transitionMatrix); +template void StandardRewardModel::reduceToStateBasedRewards(storm::storage::SparseMatrix const& transitionMatrix, + bool reduceToStateRewards, std::vector const* weights); +template void StandardRewardModel::reduceToStateBasedRewards(storm::storage::SparseMatrix const& transitionMatrix, + bool reduceToStateRewards, std::vector const* weights); +template storm::storage::BitVector StandardRewardModel::getStatesWithZeroReward( + storm::storage::SparseMatrix const& transitionMatrix) const; +template storm::storage::BitVector StandardRewardModel::getChoicesWithZeroReward( + storm::storage::SparseMatrix const& transitionMatrix) const; +template class StandardRewardModel; +template std::ostream& operator<< (std::ostream& out, StandardRewardModel const& rewardModel); #endif } // namespace sparse diff --git a/src/storm/models/sparse/StochasticTwoPlayerGame.cpp b/src/storm/models/sparse/StochasticTwoPlayerGame.cpp index 5fd740d680..27555046e3 100644 --- a/src/storm/models/sparse/StochasticTwoPlayerGame.cpp +++ b/src/storm/models/sparse/StochasticTwoPlayerGame.cpp @@ -64,9 +64,11 @@ template class StochasticTwoPlayerGame; #ifdef STORM_HAVE_CARL template class StochasticTwoPlayerGame>; +template class StochasticTwoPlayerGame>; template class StochasticTwoPlayerGame; template class StochasticTwoPlayerGame; template class StochasticTwoPlayerGame; +template class StochasticTwoPlayerGame; #endif diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp index 50fac6d682..508d427a73 100644 --- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp @@ -123,7 +123,7 @@ void IterativeMinMaxLinearEquationSolver::setUpViOperat // The trivial row grouping minmax operator makes sense over intervals. viOperatorTriv = std::make_shared>(); viOperatorTriv->setMatrixBackwards(*this->A); - if constexpr (!std::is_same_v) { + if constexpr (!std::is_same_v and !std::is_same_v) { // It might be that someone is using a minmaxlinearequationsolver with an advanced VI algorithm // but is just passing a DTMC over doubles. In this case we need to populate this VI operator. // It behaves exactly the same as the trivial row grouping operator, but it is currently hardcoded @@ -155,7 +155,7 @@ void IterativeMinMaxLinearEquationSolver::setUpViOperat template void IterativeMinMaxLinearEquationSolver::extractScheduler(std::vector& x, std::vector const& b, OptimizationDirection const& dir, bool updateX, bool robust) const { - if (std::is_same_v && this->A->hasTrivialRowGrouping()) { + if ((std::is_same_v || std::is_same_v) && this->A->hasTrivialRowGrouping()) { // Create robust scheduler index if it doesn't exist yet if (!this->robustSchedulerIndex) { this->robustSchedulerIndex = std::vector(x.size(), 0); @@ -189,7 +189,8 @@ void IterativeMinMaxLinearEquationSolver::extractSchedu setUpViOperator(); } if (viOperatorTriv) { - if constexpr (std::is_same() && std::is_same()) { + if constexpr (std::is_same() && std::is_same() || + std::is_same_v && std::is_same_v) { storm::solver::helper::SchedulerTrackingHelper schedHelper(viOperatorTriv); schedHelper.computeScheduler(x, b, dir, *this->schedulerChoices, robust, updateX ? &x : nullptr, this->robustSchedulerIndex); } else { @@ -206,8 +207,8 @@ template bool IterativeMinMaxLinearEquationSolver::solveInducedEquationSystem( Environment const& env, std::unique_ptr>& linearEquationSolver, std::vector const& scheduler, std::vector& x, std::vector& subB, std::vector const& originalB, OptimizationDirection dir) const { - if constexpr (std::is_same_v) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement solving induced equation systems for interval-based models outside of robust VI."); // Implementing this requires linear equation systems with different value types and solution types (or some appropriate casting) @@ -239,7 +240,7 @@ bool IterativeMinMaxLinearEquationSolver::solveInducedE for (uint64_t i = 0; i < row.getNumberOfEntries(); i++, schedulerIterator++) { if (!utility::isZero(probLeft)) { auto const& entry = rowIter[*schedulerIterator]; - auto const diameter = entry.getValue().upper() - entry.getValue().lower(); + SolutionType const diameter = entry.getValue().upper() - entry.getValue().lower(); auto const value = utility::min(probLeft, diameter); tmp[*schedulerIterator] += value; probLeft -= value; @@ -322,7 +323,7 @@ template bool IterativeMinMaxLinearEquationSolver::performPolicyIteration( Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b, std::vector&& initialPolicy) const { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement policy iteration for interval-based models."); return false; } else { @@ -448,7 +449,7 @@ MinMaxLinearEquationSolverRequirements IterativeMinMaxLinearEquationSolver) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_ASSERT(!needsLinEqSolver, "Intervals should not require a linear equation solver."); // nothing to be done; } else if (needsLinEqSolver) { @@ -543,7 +544,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsOptimisticValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement optimistic value iteration for interval-based models."); return false; } else { @@ -713,8 +714,8 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsIntervalIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement intervaliteration for interval-based models"); + if constexpr (std::is_same_v || std::is_same_v) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement interval iteration for interval-based models"); return false; } else { setUpViOperator(); @@ -756,7 +757,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsSoundValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "SoundVI does not handle interval-based models"); return false; } else { @@ -808,7 +809,7 @@ bool IterativeMinMaxLinearEquationSolver::solveEquation template bool IterativeMinMaxLinearEquationSolver::solveEquationsViToPi(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "ViToPi does not handle interval-based models"); return false; } @@ -843,7 +844,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsRationalSearch(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Rational search does not handle interval-based models"); return false; } else { @@ -915,6 +916,7 @@ void IterativeMinMaxLinearEquationSolver::clearCache() template class IterativeMinMaxLinearEquationSolver; template class IterativeMinMaxLinearEquationSolver; template class IterativeMinMaxLinearEquationSolver; +template class IterativeMinMaxLinearEquationSolver; } // namespace solver } // namespace storm diff --git a/src/storm/solver/LinearEquationSolver.cpp b/src/storm/solver/LinearEquationSolver.cpp index a0afd56f88..fdecf4cf85 100644 --- a/src/storm/solver/LinearEquationSolver.cpp +++ b/src/storm/solver/LinearEquationSolver.cpp @@ -153,7 +153,7 @@ template std::unique_ptr> GeneralLinearEquationSolverFactory::create(Environment const& env) const { EquationSolverType type = env.solver().getLinearEquationSolverType(); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not implemented interval-based linear equation solvers"); } diff --git a/src/storm/solver/MinMaxLinearEquationSolver.cpp b/src/storm/solver/MinMaxLinearEquationSolver.cpp index 7f9a506bcb..690c3bf42b 100644 --- a/src/storm/solver/MinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/MinMaxLinearEquationSolver.cpp @@ -247,19 +247,19 @@ std::unique_ptr> GeneralMinM result = std::make_unique>( std::make_unique>()); } else if (method == MinMaxMethod::Topological) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_ERROR("Topological method not implemented for ValueType==Interval."); } else { result = std::make_unique>(); } } else if (method == MinMaxMethod::LinearProgramming || method == MinMaxMethod::ViToLp) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_ERROR("LP method not implemented for ValueType==Interval."); } else { result = std::make_unique>(storm::utility::solver::getLpSolverFactory()); } } else if (method == MinMaxMethod::Acyclic) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { STORM_LOG_ERROR("Acyclic method not implemented for ValueType==Interval"); } else { result = std::make_unique>(); @@ -306,4 +306,8 @@ template class GeneralMinMaxLinearEquationSolverFactory; template class MinMaxLinearEquationSolver; template class MinMaxLinearEquationSolverFactory; template class GeneralMinMaxLinearEquationSolverFactory; + +template class MinMaxLinearEquationSolver; +template class MinMaxLinearEquationSolverFactory; +template class GeneralMinMaxLinearEquationSolverFactory; } // namespace storm::solver diff --git a/src/storm/solver/SolveGoal.cpp b/src/storm/solver/SolveGoal.cpp index 82eae70775..781b52ac02 100644 --- a/src/storm/solver/SolveGoal.cpp +++ b/src/storm/solver/SolveGoal.cpp @@ -149,6 +149,7 @@ template class SolveGoal; template class SolveGoal; template class SolveGoal; template class SolveGoal; +template class SolveGoal; } // namespace solver } // namespace storm diff --git a/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp b/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp index e65879631c..90fbaf2ec9 100644 --- a/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp @@ -50,5 +50,6 @@ void StandardMinMaxLinearEquationSolver::setMatrix(stor template class StandardMinMaxLinearEquationSolver; template class StandardMinMaxLinearEquationSolver; template class StandardMinMaxLinearEquationSolver; +template class StandardMinMaxLinearEquationSolver; } // namespace storm::solver diff --git a/src/storm/solver/helper/SchedulerTrackingHelper.cpp b/src/storm/solver/helper/SchedulerTrackingHelper.cpp index 1dde116e50..a83b5b8244 100644 --- a/src/storm/solver/helper/SchedulerTrackingHelper.cpp +++ b/src/storm/solver/helper/SchedulerTrackingHelper.cpp @@ -132,5 +132,7 @@ template class SchedulerTrackingHelper; template class SchedulerTrackingHelper; template class SchedulerTrackingHelper; template class SchedulerTrackingHelper; +template class SchedulerTrackingHelper; +template class SchedulerTrackingHelper; } // namespace storm::solver::helper diff --git a/src/storm/solver/helper/ValueIterationHelper.cpp b/src/storm/solver/helper/ValueIterationHelper.cpp index 838fc5ba8f..5302757813 100644 --- a/src/storm/solver/helper/ValueIterationHelper.cpp +++ b/src/storm/solver/helper/ValueIterationHelper.cpp @@ -149,5 +149,7 @@ template class ValueIterationHelper; template class ValueIterationHelper; template class ValueIterationHelper; template class ValueIterationHelper; +template class ValueIterationHelper; +template class ValueIterationHelper; } // namespace storm::solver::helper diff --git a/src/storm/solver/helper/ValueIterationOperator.cpp b/src/storm/solver/helper/ValueIterationOperator.cpp index dfb85a5eec..81b4988216 100644 --- a/src/storm/solver/helper/ValueIterationOperator.cpp +++ b/src/storm/solver/helper/ValueIterationOperator.cpp @@ -203,5 +203,7 @@ template class ValueIterationOperator; template class ValueIterationOperator; template class ValueIterationOperator; template class ValueIterationOperator; +template class ValueIterationOperator; +template class ValueIterationOperator; } // namespace storm::solver::helper diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index 86f65f890e..8d157aae0d 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -269,7 +269,7 @@ class ValueIterationOperator { template auto applyRow(std::vector::const_iterator& matrixColumnIt, typename std::vector::const_iterator& matrixValueIt, OperandType const& operand, OffsetType const& offsets, uint64_t offsetIndex) const { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { return applyRowRobust(matrixColumnIt, matrixValueIt, operand, offsets, offsetIndex); } else { return applyRowStandard(matrixColumnIt, matrixValueIt, operand, offsets, offsetIndex); @@ -459,6 +459,12 @@ class ValueIterationOperator { storage::BitVector hasOnlyConstants; }; + template + struct ApplyCache { + mutable std::vector>> robustOrder; + storage::BitVector hasOnlyConstants; + }; + /*! * Cache for robust value iteration, empty struct for other ValueTypes than storm::Interval. */ diff --git a/src/storm/storage/Distribution.cpp b/src/storm/storage/Distribution.cpp index d7796fbeb8..0f8e48f7be 100644 --- a/src/storm/storage/Distribution.cpp +++ b/src/storm/storage/Distribution.cpp @@ -227,6 +227,11 @@ template std::ostream& operator<<(std::ostream& out, Distribution; template std::ostream& operator<<(std::ostream& out, Distribution const& distribution); +template class Distribution; +template std::ostream& operator<<(std::ostream& out, Distribution const& distribution); +template class Distribution; +template std::ostream& operator<<(std::ostream& out, Distribution const& distribution); + #endif } // namespace storage } // namespace storm diff --git a/src/storm/storage/MaximalEndComponentDecomposition.cpp b/src/storm/storage/MaximalEndComponentDecomposition.cpp index 4d4dc1ed7c..ac4415575c 100644 --- a/src/storm/storage/MaximalEndComponentDecomposition.cpp +++ b/src/storm/storage/MaximalEndComponentDecomposition.cpp @@ -252,6 +252,10 @@ template class MaximalEndComponentDecomposition; template MaximalEndComponentDecomposition::MaximalEndComponentDecomposition( storm::models::sparse::NondeterministicModel const& model); +template class MaximalEndComponentDecomposition; +template MaximalEndComponentDecomposition::MaximalEndComponentDecomposition( + storm::models::sparse::NondeterministicModel const& model); + template class MaximalEndComponentDecomposition; template MaximalEndComponentDecomposition::MaximalEndComponentDecomposition( storm::models::sparse::NondeterministicModel const& model); diff --git a/src/storm/storage/Scheduler.cpp b/src/storm/storage/Scheduler.cpp index 108f2b5f31..21aba6bf54 100644 --- a/src/storm/storage/Scheduler.cpp +++ b/src/storm/storage/Scheduler.cpp @@ -385,6 +385,7 @@ template class Scheduler; template class Scheduler; template class Scheduler; template class Scheduler; +template class Scheduler; } // namespace storage } // namespace storm diff --git a/src/storm/storage/SchedulerChoice.cpp b/src/storm/storage/SchedulerChoice.cpp index cf810cd8d6..b5549edb70 100644 --- a/src/storm/storage/SchedulerChoice.cpp +++ b/src/storm/storage/SchedulerChoice.cpp @@ -75,6 +75,8 @@ template class SchedulerChoice; template std::ostream& operator<<(std::ostream& out, SchedulerChoice const& schedulerChoice); template class SchedulerChoice; template std::ostream& operator<<(std::ostream& out, SchedulerChoice const& schedulerChoice); +template class SchedulerChoice; +template std::ostream& operator<<(std::ostream& out, SchedulerChoice const& schedulerChoice); } // namespace storage } // namespace storm diff --git a/src/storm/storage/SparseMatrix.cpp b/src/storm/storage/SparseMatrix.cpp index 3c012646e2..1a4d047d9a 100644 --- a/src/storm/storage/SparseMatrix.cpp +++ b/src/storm/storage/SparseMatrix.cpp @@ -2740,6 +2740,20 @@ template std::vector SparseMatrix::getPointwiseProduc template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; + +// Rational Intervals +template std::vector SparseMatrix::getPointwiseProductRowSumVector( + storm::storage::SparseMatrix const& otherMatrix) const; +template class MatrixEntry::index_type, RationalInterval>; +template std::ostream& operator<<(std::ostream& out, MatrixEntry::index_type, RationalInterval> const& entry); +template class SparseMatrixBuilder; +template class SparseMatrix; +template std::ostream& operator<<(std::ostream& out, SparseMatrix const& matrix); +template std::vector SparseMatrix::getPointwiseProductRowSumVector( + storm::storage::SparseMatrix const& otherMatrix) const; +template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; + +template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; #endif } // namespace storage diff --git a/src/storm/storage/StronglyConnectedComponentDecomposition.cpp b/src/storm/storage/StronglyConnectedComponentDecomposition.cpp index e6013c4d5a..eb25b5a74e 100644 --- a/src/storm/storage/StronglyConnectedComponentDecomposition.cpp +++ b/src/storm/storage/StronglyConnectedComponentDecomposition.cpp @@ -343,5 +343,6 @@ template class StronglyConnectedComponentDecomposition; template class StronglyConnectedComponentDecomposition; template class StronglyConnectedComponentDecomposition; template class StronglyConnectedComponentDecomposition; +template class StronglyConnectedComponentDecomposition; } // namespace storm::storage diff --git a/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp b/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp index d1a20376f3..3d60296b6f 100644 --- a/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp +++ b/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp @@ -133,9 +133,11 @@ MemoryStructure MemoryStructureBuilder::buildTrivial template class MemoryStructureBuilder; template class MemoryStructureBuilder>; +template class MemoryStructureBuilder>; template class MemoryStructureBuilder; template class MemoryStructureBuilder; template class MemoryStructureBuilder; +template class MemoryStructureBuilder; } // namespace storage } // namespace storm diff --git a/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp b/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp index a16f2e2ced..5fb52b8fe0 100644 --- a/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp +++ b/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp @@ -562,9 +562,11 @@ storm::storage::MemoryStructure const& SparseModelMemoryProduct; template class SparseModelMemoryProduct>; +template class SparseModelMemoryProduct>; template class SparseModelMemoryProduct; template class SparseModelMemoryProduct; template class SparseModelMemoryProduct; +template class SparseModelMemoryProduct; } // namespace storage } // namespace storm diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index 7db11d701d..777f3bfb99 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -78,4 +78,5 @@ storm::Interval AddUncertainty::addUncertainty(ValueType const& vt, d } template class AddUncertainty; +template class AddUncertainty; } // namespace storm::transformer \ No newline at end of file diff --git a/src/storm/transformer/SubsystemBuilder.cpp b/src/storm/transformer/SubsystemBuilder.cpp index 67e00add30..6689543622 100644 --- a/src/storm/transformer/SubsystemBuilder.cpp +++ b/src/storm/transformer/SubsystemBuilder.cpp @@ -229,6 +229,10 @@ template SubsystemBuilderReturnType> const& originalModel, storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, SubsystemBuilderOptions options = SubsystemBuilderOptions()); +template SubsystemBuilderReturnType> buildSubsystem( + storm::models::sparse::Model> const& originalModel, + storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, + SubsystemBuilderOptions options = SubsystemBuilderOptions()); template SubsystemBuilderReturnType buildSubsystem(storm::models::sparse::Model const& originalModel, storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, @@ -242,6 +246,10 @@ template SubsystemBuilderReturnType buildSubsystem(storm::model storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, SubsystemBuilderOptions options = SubsystemBuilderOptions()); +template SubsystemBuilderReturnType buildSubsystem(storm::models::sparse::Model const& originalModel, + storm::storage::BitVector const& subsystemStates, + storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, + SubsystemBuilderOptions options = SubsystemBuilderOptions()); } // namespace transformer } // namespace storm diff --git a/src/storm/utility/ConstantsComparator.cpp b/src/storm/utility/ConstantsComparator.cpp index c082cb5a29..e5f939299f 100644 --- a/src/storm/utility/ConstantsComparator.cpp +++ b/src/storm/utility/ConstantsComparator.cpp @@ -109,6 +109,7 @@ template class ConstantsComparator; template class ConstantsComparator; template class ConstantsComparator; template class ConstantsComparator; +template class ConstantsComparator; #endif } // namespace utility } // namespace storm diff --git a/src/storm/utility/builder.cpp b/src/storm/utility/builder.cpp index 8a354bcf55..58ea84c0ef 100644 --- a/src/storm/utility/builder.cpp +++ b/src/storm/utility/builder.cpp @@ -42,12 +42,17 @@ template std::shared_ptr> buildModelFromCom template std::shared_ptr>> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents>&& components); +template std::shared_ptr>> buildModelFromComponents( + storm::models::ModelType modelType, + storm::storage::sparse::ModelComponents>&& components); template std::shared_ptr> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); template std::shared_ptr> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); template std::shared_ptr> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); +template std::shared_ptr> buildModelFromComponents( + storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); } // namespace builder } // namespace utility diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index 031614be74..4623b44dc6 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -754,6 +754,11 @@ bool isConstant(storm::Interval const& a) { return a.isPointInterval(); } +template<> +bool isConstant(storm::RationalInterval const& a) { + return a.isPointInterval(); +} + template<> bool isInfinity(storm::RationalFunction const& a) { // FIXME: this should be treated more properly. @@ -933,6 +938,11 @@ storm::Interval convertNumber(double const& number) { return storm::Interval(number); } +template<> +storm::RationalInterval convertNumber(double const& number) { + return storm::RationalInterval(convertNumber(number)); +} + #if defined(STORM_HAVE_GMP) template<> storm::Interval convertNumber(storm::GmpRationalNumber const& n) { @@ -944,6 +954,17 @@ storm::GmpRationalNumber convertNumber(storm::Interval const& number) { STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); return convertNumber(number.lower()); } + +template<> +storm::RationalInterval convertNumber(storm::GmpRationalNumber const& n) { + return storm::RationalInterval(convertNumber(n)); +} + +template<> +storm::GmpRationalNumber convertNumber(storm::RationalInterval const& number) { + STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); + return convertNumber(number.lower()); +} #endif #if defined(STORM_HAVE_CLN) @@ -957,6 +978,17 @@ storm::ClnRationalNumber convertNumber(storm::Interval const& number) { STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); return convertNumber(number.lower()); } + +template<> +storm::RationalInterval convertNumber(storm::ClnRationalNumber const& n) { + return storm::RationalInterval(convertNumber(n)); +} + +template<> +storm::ClnRationalNumber convertNumber(storm::RationalInterval const& number) { + STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); + return convertNumber(number.lower()); +} #endif template<> @@ -965,11 +997,22 @@ double convertNumber(storm::Interval const& number) { return number.lower(); } +template<> +double convertNumber(storm::RationalInterval const& number) { + STORM_LOG_ASSERT(number.isPointInterval(), "Rational interval must be a point interval to convert"); + return convertNumber(number.lower()); +} + template<> storm::Interval abs(storm::Interval const& interval) { return interval.abs(); } +template<> +storm::RationalInterval abs(storm::RationalInterval const& interval) { + return interval.abs(); +} + // Explicit instantiations. // double @@ -1109,6 +1152,16 @@ template bool isInfinity(Interval const& value); template bool isAlmostZero(Interval const& value); template std::string to_string(storm::Interval const& value); + +// Instantiations for intervals. +template RationalInterval one(); +template RationalInterval zero(); +template bool isOne(RationalInterval const& value); +template bool isZero(RationalInterval const& value); +template bool isInfinity(RationalInterval const& value); +template bool isAlmostZero(RationalInterval const& value); + +template std::string to_string(storm::RationalInterval const& value); #endif } // namespace utility diff --git a/src/storm/utility/graph.cpp b/src/storm/utility/graph.cpp index 2a140012ee..b3d9850398 100644 --- a/src/storm/utility/graph.cpp +++ b/src/storm/utility/graph.cpp @@ -1979,6 +1979,9 @@ template storm::storage::BitVector performProb0E( template storm::storage::BitVector performProb0E( storm::models::sparse::NondeterministicModel> const& model, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); +template storm::storage::BitVector performProb0E( + storm::models::sparse::NondeterministicModel> const& model, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); #endif template storm::storage::BitVector performProb0E(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, @@ -1992,6 +1995,9 @@ template storm::storage::BitVector performProb1A( template storm::storage::BitVector performProb1A( storm::models::sparse::NondeterministicModel> const& model, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); +template storm::storage::BitVector performProb1A( + storm::models::sparse::NondeterministicModel> const& model, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); #endif template storm::storage::BitVector performProb1A(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, @@ -2287,6 +2293,135 @@ template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix getTopologicalSort(storm::storage::SparseMatrix const& matrix, std::vector const& firstStates); // End storm::interval +// Instantiations for storm::Rationalinterval + +template storm::storage::BitVector getReachableOneStep(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::BitVector const& initialStates); + +template storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates, + storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps, + boost::optional const& choiceFilter); + +template storm::storage::BitVector getBsccCover(storm::storage::SparseMatrix const& transitionMatrix); + +template bool hasCycle(storm::storage::SparseMatrix const& transitionMatrix, boost::optional const& subsystem); + +template bool checkIfECWithChoiceExists(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& subsystem, + storm::storage::BitVector const& choices); + +template std::vector getDistances(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::BitVector const& initialStates, boost::optional const& subsystem); + +template storm::storage::BitVector performProbGreater0(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + bool useStepBound = false, uint_fast64_t maximalSteps = 0); + +template storm::storage::BitVector performProb1(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + storm::storage::BitVector const& statesWithProbabilityGreater0); + +template storm::storage::BitVector performProb1(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template std::pair performProb01(storm::models::sparse::DeterministicModel const& model, + storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template std::pair performProb01(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template void computeSchedulerProbGreater0E(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + storm::storage::Scheduler& scheduler, boost::optional const& rowFilter); + +template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::Scheduler& scheduler); + +template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::Scheduler& scheduler); + +template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates, storm::storage::Scheduler& scheduler, + boost::optional const& rowFilter = boost::none); + +template storm::storage::BitVector performProbGreater0E(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + bool useStepBound = false, uint_fast64_t maximalSteps = 0); + +template storm::storage::BitVector performProb0A(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProb1E(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + boost::optional const& choiceConstraint = boost::none); + +template storm::storage::BitVector performProb1E(storm::models::sparse::NondeterministicModel const& model, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template std::pair performProb01Max( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template std::pair performProb01Max( + storm::models::sparse::NondeterministicModel const& model, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProbGreater0A(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + bool useStepBound = false, uint_fast64_t maximalSteps = 0, + boost::optional const& choiceConstraint = boost::none); + +template storm::storage::BitVector performProb0E(storm::models::sparse::NondeterministicModel const& model, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProb0E(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProb1A(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template std::pair performProb01Min( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template std::pair performProb01Min( + storm::models::sparse::NondeterministicModel const& model, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& player1RowGrouping, + storm::storage::SparseMatrix const& player1BackwardTransitions, + std::vector const& player2BackwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction, + storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair); + +template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& player1RowGrouping, + storm::storage::SparseMatrix const& player1BackwardTransitions, + std::vector const& player2BackwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction, + storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair, + boost::optional const& player1Candidates); + +template std::vector getTopologicalSort(storm::storage::SparseMatrix const& matrix, std::vector const& firstStates); +// End storm::Rationalinterval template storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates, From f950cd7fec60540c3c6bfb303924f457d678b316 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 21 May 2025 10:24:37 +0200 Subject: [PATCH 023/102] fix one linking error --- CMakeLists.txt | 2 +- src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp | 2 +- .../helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp | 2 ++ src/storm/utility/constants.cpp | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06d4c92780..6269817dc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,7 +297,7 @@ if (STORM_COMPILER_CLANG OR STORM_COMPILER_APPLECLANG) set(CLANG_STDLIB libc++) endif() - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${CLANG_STDLIB} -ftemplate-depth=1024") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${CLANG_STDLIB} -ftemplate-depth=1024 -ftemplate-backtrace-limit=0 -ferror-limit=10000") set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") if(LINUX) diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index c06a027a4f..f56e352183 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -286,7 +286,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); if (rewardPathFormula.isMultiDimensional() || rewardPathFormula.getTimeBoundReference().isRewardBound()) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { throw exceptions::NotImplementedException() << "Multi-reward bounded is not supported with interval models"; } else { STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp index 6f3533e6a8..552122bbc2 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp @@ -964,6 +964,8 @@ template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; +// template class MultiDimensionalRewardUnfolding; +// template class MultiDimensionalRewardUnfolding; } // namespace rewardbounded } // namespace helper } // namespace modelchecker diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index 4623b44dc6..1a82abaf74 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -39,6 +39,7 @@ bool isOne(ValueType const& a) { template bool isZero(ValueType const& a) { + static_assert(not std::is_same_v, __gmp_expr<__mpq_struct, __mpq_struct>, __gmp_binary_minus> > >, "Missing template instantiation!"); return a == zero(); } From eafe06db5af18883f7ad704066c87d239ca7dc05 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 21 May 2025 13:09:50 +0200 Subject: [PATCH 024/102] Parse rational interval models and fix bug --- .../parser/DirectEncodingParser.cpp | 1 + src/storm-parsers/parser/ValueParser.cpp | 48 +++++++++++++++++++ .../solver/helper/ValueIterationOperator.h | 2 +- .../storm/parser/DirectEncodingParserTest.cpp | 9 ++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/storm-parsers/parser/DirectEncodingParser.cpp b/src/storm-parsers/parser/DirectEncodingParser.cpp index a4f85cf937..294ad7e4e9 100644 --- a/src/storm-parsers/parser/DirectEncodingParser.cpp +++ b/src/storm-parsers/parser/DirectEncodingParser.cpp @@ -430,6 +430,7 @@ template class DirectEncodingParser; template class DirectEncodingParser; template class DirectEncodingParser; template class DirectEncodingParser; +template class DirectEncodingParser; } // namespace parser } // namespace storm diff --git a/src/storm-parsers/parser/ValueParser.cpp b/src/storm-parsers/parser/ValueParser.cpp index 5de5fef96d..87838acf84 100644 --- a/src/storm-parsers/parser/ValueParser.cpp +++ b/src/storm-parsers/parser/ValueParser.cpp @@ -117,6 +117,51 @@ bool parseInterval(std::string const& value, storm::Interval& result) { return true; } +bool parseRationalInterval(std::string const& value, storm::RationalInterval& result) { + // Try whether it is a constant. + if (storm::RationalNumber pointResult; parseNumber(value, pointResult)) { + result = storm::RationalInterval(pointResult); + return true; + } + + std::string intermediate = value; + boost::trim(intermediate); + carl::BoundType leftBound; + carl::BoundType rightBound; + if (intermediate.front() == '(') { + leftBound = carl::BoundType::STRICT; + } else if (intermediate.front() == '[') { + leftBound = carl::BoundType::WEAK; + } else { + return false; // Expect start with '(' or '['. + } + if (intermediate.back() == ')') { + rightBound = carl::BoundType::STRICT; + } else if (intermediate.back() == ']') { + rightBound = carl::BoundType::WEAK; + } else { + return false; // Expected end with ')' or ']'. + } + intermediate = intermediate.substr(1, intermediate.size() - 2); + + std::vector words; + boost::split(words, intermediate, boost::is_any_of(",")); + if (words.size() != 2) { + return false; // Did not find exactly one comma. + } + storm::RationalNumber leftVal, rightVal; + boost::trim(words[0]); + if (!parseNumber(words[0], leftVal)) { + return false; // lower value of interval invalid. + } + boost::trim(words[1]); + if (!parseNumber(words[1], rightVal)) { + return false; // upper value of interval invalid. + } + result = storm::RationalInterval(leftVal, leftBound, rightVal, rightBound); + return true; +} + template bool parseNumber(std::string const& value, NumberType& result) { if constexpr (std::is_same_v) { @@ -125,6 +170,8 @@ bool parseNumber(std::string const& value, NumberType& result) { return carl::try_parse(value, result); } else if constexpr (std::is_same_v) { return parseInterval(value, result); + } else if constexpr (std::is_same_v) { + return parseRationalInterval(value, result); } else { return boost::conversion::try_lexical_convert(value, result); } @@ -135,6 +182,7 @@ template class ValueParser; template class ValueParser; template class ValueParser; template class ValueParser; +template class ValueParser; template std::size_t parseNumber(std::string const&); diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index 8d157aae0d..4d91c181d7 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -337,7 +337,7 @@ class ValueIterationOperator { result += operand[*matrixColumnIt] * lower; } remainingValue -= lower; - auto const diameter = matrixValueIt->upper() - lower; + SolutionType const diameter = matrixValueIt->upper() - lower; if (!storm::utility::isZero(diameter)) { applyCache.robustOrder.emplace_back(operand[*matrixColumnIt], std::make_pair(diameter, orderCounter)); } diff --git a/src/test/storm/parser/DirectEncodingParserTest.cpp b/src/test/storm/parser/DirectEncodingParserTest.cpp index f8397ca595..df63527db9 100644 --- a/src/test/storm/parser/DirectEncodingParserTest.cpp +++ b/src/test/storm/parser/DirectEncodingParserTest.cpp @@ -97,3 +97,12 @@ TEST(DirectEncodingParserTest, IntervalDtmcTest) { ASSERT_EQ(613ul, dtmc->getNumberOfStates()); EXPECT_TRUE(modelPtr->hasUncertainty()); } + +TEST(DirectEncodingParserTest, RationalIntervalDtmcTest) { + std::shared_ptr> modelPtr = + storm::parser::DirectEncodingParser::parseModel(STORM_TEST_RESOURCES_DIR "/idtmc/brp-16-2.drn"); + std::shared_ptr> dtmc = modelPtr->as>(); + ASSERT_EQ(storm::models::ModelType::Dtmc, modelPtr->getType()); + ASSERT_EQ(613ul, dtmc->getNumberOfStates()); + EXPECT_TRUE(modelPtr->hasUncertainty()); +} From 81be1acb9b322754715b05c074523d9c3bdf0cd2 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 22 May 2025 12:17:50 +0200 Subject: [PATCH 025/102] small fixes --- CMakeLists.txt | 2 +- src/storm-cli-utilities/model-handling.h | 14 +++++++++++--- src/storm/io/DirectEncodingExporter.cpp | 2 ++ src/storm/models/sparse/Model.cpp | 2 +- src/storm/settings/modules/GeneralSettings.cpp | 7 +++++++ src/storm/settings/modules/GeneralSettings.h | 8 ++++++++ src/storm/solver/helper/ValueIterationOperator.h | 12 ++++++------ src/storm/utility/NumberTraits.h | 6 ++++++ 8 files changed, 42 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6269817dc4..06d4c92780 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,7 +297,7 @@ if (STORM_COMPILER_CLANG OR STORM_COMPILER_APPLECLANG) set(CLANG_STDLIB libc++) endif() - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${CLANG_STDLIB} -ftemplate-depth=1024 -ftemplate-backtrace-limit=0 -ferror-limit=10000") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${CLANG_STDLIB} -ftemplate-depth=1024") set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") if(LINUX) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 3175d241c2..c48af5e485 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -162,7 +162,7 @@ struct ModelProcessingInformation { bool transformToJani; // Which data type is to be used for numbers ... - enum class ValueType { FinitePrecision, Exact, Parametric }; + enum class ValueType { FinitePrecision, Exact, Parametric, FinitePrecisionInterval, ExactInterval }; ValueType buildValueType; // ... during model building ValueType verificationValueType; // ... during model verification @@ -230,9 +230,17 @@ inline ModelProcessingInformation getModelProcessingInformation(SymbolicInput co if (generalSettings.isParametricSet()) { mpi.verificationValueType = ModelProcessingInformation::ValueType::Parametric; } else if (generalSettings.isExactSet()) { - mpi.verificationValueType = ModelProcessingInformation::ValueType::Exact; + if (generalSettings.isIntervalSet()) { + mpi.verificationValueType = ModelProcessingInformation::ValueType::ExactInterval; + } else { + mpi.verificationValueType = ModelProcessingInformation::ValueType::Exact; + } } else { - mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecision; + if (generalSettings.isIntervalSet()) { + mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecisionInterval; + } else { + mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecision; + } } auto originalVerificationValueType = mpi.verificationValueType; diff --git a/src/storm/io/DirectEncodingExporter.cpp b/src/storm/io/DirectEncodingExporter.cpp index e3cfcb4fd7..962a09243d 100644 --- a/src/storm/io/DirectEncodingExporter.cpp +++ b/src/storm/io/DirectEncodingExporter.cpp @@ -280,5 +280,7 @@ template void explicitExportSparseModel(std::ostream& o std::vector const& parameters, DirectEncodingOptions const& options); template void explicitExportSparseModel(std::ostream& os, std::shared_ptr> sparseModel, std::vector const& parameters, DirectEncodingOptions const& options); +template void explicitExportSparseModel(std::ostream& os, std::shared_ptr> sparseModel, + std::vector const& parameters, DirectEncodingOptions const& options); } // namespace io } // namespace storm diff --git a/src/storm/models/sparse/Model.cpp b/src/storm/models/sparse/Model.cpp index 09b41089cb..cabf7b40e7 100644 --- a/src/storm/models/sparse/Model.cpp +++ b/src/storm/models/sparse/Model.cpp @@ -652,7 +652,7 @@ bool Model::supportsParameters() const { template bool Model::supportsUncertainty() const { - return std::is_same::value; + return std::is_same_v || std::is_same_v; } template diff --git a/src/storm/settings/modules/GeneralSettings.cpp b/src/storm/settings/modules/GeneralSettings.cpp index d2efd632e8..6ae58ce4ff 100644 --- a/src/storm/settings/modules/GeneralSettings.cpp +++ b/src/storm/settings/modules/GeneralSettings.cpp @@ -32,6 +32,7 @@ const std::string GeneralSettings::bisimulationOptionShortName = "bisim"; const std::string GeneralSettings::parametricOptionName = "parametric"; const std::string GeneralSettings::exactOptionName = "exact"; const std::string GeneralSettings::soundOptionName = "sound"; +const std::string GeneralSettings::intervalOptionName = "interval"; GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { this->addOption( @@ -85,6 +86,8 @@ GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { .build()) .build()); this->addOption(storm::settings::OptionBuilder(moduleName, soundOptionName, false, "Sets whether to force sound model checking.").build()); + this->addOption( + storm::settings::OptionBuilder(moduleName, intervalOptionName, false, "Sets whether to enable interval model checking.").build()); } bool GeneralSettings::isHelpSet() const { @@ -152,6 +155,10 @@ bool GeneralSettings::isSoundSet() const { return this->getOption(soundOptionName).getHasOptionBeenSet(); } +bool GeneralSettings::isIntervalSet() const { + return this->getOption(intervalOptionName).getHasOptionBeenSet(); +} + void GeneralSettings::finalize() { // Intentionally left empty. } diff --git a/src/storm/settings/modules/GeneralSettings.h b/src/storm/settings/modules/GeneralSettings.h index 1723583b14..2e2e12620f 100644 --- a/src/storm/settings/modules/GeneralSettings.h +++ b/src/storm/settings/modules/GeneralSettings.h @@ -123,6 +123,13 @@ class GeneralSettings : public ModuleSettings { */ bool isSoundSet() const; + /*! + * Retrieves whether the option enabling interval models is set. + * + * @return True if the option was set + */ + bool isIntervalSet() const; + bool check() const override; void finalize() override; @@ -149,6 +156,7 @@ class GeneralSettings : public ModuleSettings { static const std::string parametricOptionName; static const std::string exactOptionName; static const std::string soundOptionName; + static const std::string intervalOptionName; }; } // namespace modules diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index 4d91c181d7..72d2b5af0b 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -309,13 +309,13 @@ class ValueIterationOperator { auto applyRowRobust(std::vector::const_iterator& matrixColumnIt, typename std::vector::const_iterator& matrixValueIt, OperandType const& operand, OffsetType const& offsets, uint64_t offsetIndex) const { STORM_LOG_ASSERT(*matrixColumnIt >= StartOfRowIndicator, "VI Operator in invalid state."); - auto result{robustInitializeRowRes(operand, offsets, offsetIndex)}; + SolutionType result{robustInitializeRowRes(operand, offsets, offsetIndex)}; applyCache.robustOrder.clear(); if (applyCache.hasOnlyConstants.get(offsetIndex)) { for (++matrixColumnIt; *matrixColumnIt < StartOfRowIndicator; ++matrixColumnIt, ++matrixValueIt) { - auto const lower = matrixValueIt->lower(); + SolutionType const lower = matrixValueIt->lower(); if constexpr (isPair::value) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Value Iteration is not implemented with pairs and interval-models."); // Notice the unclear semantics here in terms of how to order things. @@ -329,7 +329,7 @@ class ValueIterationOperator { SolutionType remainingValue{storm::utility::one()}; uint64_t orderCounter = 0; for (++matrixColumnIt; *matrixColumnIt < StartOfRowIndicator; ++matrixColumnIt, ++matrixValueIt, ++orderCounter) { - auto const lower = matrixValueIt->lower(); + SolutionType const lower = matrixValueIt->lower(); if constexpr (isPair::value) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Value Iteration is not implemented with pairs and interval-models."); // Notice the unclear semantics here in terms of how to order things. @@ -337,8 +337,8 @@ class ValueIterationOperator { result += operand[*matrixColumnIt] * lower; } remainingValue -= lower; - SolutionType const diameter = matrixValueIt->upper() - lower; - if (!storm::utility::isZero(diameter)) { + SolutionType const diameter = static_cast(- lower + matrixValueIt->upper()); + if (!storm::utility::isZero(diameter)) { applyCache.robustOrder.emplace_back(operand[*matrixColumnIt], std::make_pair(diameter, orderCounter)); } } @@ -350,7 +350,7 @@ class ValueIterationOperator { std::sort(applyCache.robustOrder.begin(), applyCache.robustOrder.end(), cmp); for (auto const& pair : applyCache.robustOrder) { - auto availableMass = std::min(pair.second.first, remainingValue); + SolutionType availableMass = std::min(pair.second.first, remainingValue); result += availableMass * pair.first; remainingValue -= availableMass; if (storm::utility::isZero(remainingValue)) { diff --git a/src/storm/utility/NumberTraits.h b/src/storm/utility/NumberTraits.h index 0ef102199b..d37abdc3a4 100644 --- a/src/storm/utility/NumberTraits.h +++ b/src/storm/utility/NumberTraits.h @@ -40,6 +40,12 @@ struct NumberTraits { }; #endif +template<> +struct NumberTraits { + static const bool SupportsExponential = false; + static const bool IsExact = true; +}; + template<> struct NumberTraits { static const bool SupportsExponential = false; From 1610eba34b606ea83c3d11c93a69d402c4579233 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 22 May 2025 14:20:19 +0200 Subject: [PATCH 026/102] fix value iteration --- src/storm/solver/helper/ValueIterationOperator.cpp | 2 +- src/storm/solver/helper/ValueIterationOperator.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storm/solver/helper/ValueIterationOperator.cpp b/src/storm/solver/helper/ValueIterationOperator.cpp index 81b4988216..b69d509ad8 100644 --- a/src/storm/solver/helper/ValueIterationOperator.cpp +++ b/src/storm/solver/helper/ValueIterationOperator.cpp @@ -52,7 +52,7 @@ void ValueIterationOperator::setMat matrixColumns.back() = StartOfRowGroupIndicator; // This is the start of the next row group } } else { - if constexpr (std::is_same::value) { + if constexpr (std::is_same_v || std::is_same_v) { matrixColumns.push_back(StartOfRowIndicator); // Indicate start of first row for (auto rowIndex : indexRange(0, numRows)) { bool hasOnlyConstants = true; diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index 72d2b5af0b..4d413f2fbd 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -313,7 +313,7 @@ class ValueIterationOperator { applyCache.robustOrder.clear(); - if (applyCache.hasOnlyConstants.get(offsetIndex)) { + if (applyCache.hasOnlyConstants.size() > 0 && applyCache.hasOnlyConstants.get(offsetIndex)) { for (++matrixColumnIt; *matrixColumnIt < StartOfRowIndicator; ++matrixColumnIt, ++matrixValueIt) { SolutionType const lower = matrixValueIt->lower(); if constexpr (isPair::value) { From d301d8b7cf5f1410eb62035ccbd8355bbb52fea7 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 16 Jun 2025 10:33:39 +0200 Subject: [PATCH 027/102] fixes for rational interval on gcc --- src/storm/modelchecker/AbstractModelChecker.h | 33 +++++++++-------- .../prctl/SparseMdpPrctlModelChecker.h | 29 +++++++-------- .../SparsePropositionalModelChecker.h | 35 ++++++++++--------- 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/storm/modelchecker/AbstractModelChecker.h b/src/storm/modelchecker/AbstractModelChecker.h index 31d1b4673f..e52595e116 100644 --- a/src/storm/modelchecker/AbstractModelChecker.h +++ b/src/storm/modelchecker/AbstractModelChecker.h @@ -4,6 +4,7 @@ #include "storm/logic/Formulas.h" #include "storm/modelchecker/CheckTask.h" +#include "storm/models/ModelType.h" #include "storm/solver/OptimizationDirection.h" namespace storm { @@ -16,20 +17,22 @@ class CheckResult; template class AbstractModelChecker { private: - template - struct GetSolutionType { - using type = T; - }; - - template<> - struct GetSolutionType { - using type = double; - }; - - template<> - struct GetSolutionType { - using type = storm::RationalNumber; - }; + // Due to a GCC bug we have to add this dummy template type here + // https://stackoverflow.com/questions/49707184/explicit-specialization-in-non-namespace-scope-does-not-compile-in-gcc + template + struct GetSolutionType { + using type = T; + }; + + template + struct GetSolutionType { + using type = double; + }; + + template + struct GetSolutionType { + using type = storm::RationalNumber; + }; public: virtual ~AbstractModelChecker() { @@ -37,7 +40,7 @@ class AbstractModelChecker { } typedef typename ModelType::ValueType ValueType; - using SolutionType = typename GetSolutionType::type; + using SolutionType = typename GetSolutionType::type; /*! * Returns the name of the model checker class (e.g., for display in error messages). diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h index 48e9134f3b..9b71b8aadf 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h @@ -11,25 +11,26 @@ class Environment; namespace modelchecker { template class SparseMdpPrctlModelChecker : public SparsePropositionalModelChecker { - private: - template - struct GetSolutionType { - using type = T; - }; + private: + template + struct GetSolutionType { + using type = T; + }; - template<> - struct GetSolutionType { - using type = double; - }; + template + struct GetSolutionType { + using type = double; + }; + + template + struct GetSolutionType { + using type = storm::RationalNumber; + }; - template<> - struct GetSolutionType { - using type = storm::RationalNumber; - }; public: typedef typename SparseMdpModelType::ValueType ValueType; typedef typename SparseMdpModelType::RewardModelType RewardModelType; - using SolutionType = typename GetSolutionType::type; + using SolutionType = typename GetSolutionType::type; explicit SparseMdpPrctlModelChecker(SparseMdpModelType const& model); diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h index a1a63024d3..7de1792319 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h @@ -8,25 +8,28 @@ namespace modelchecker { template class SparsePropositionalModelChecker : public AbstractModelChecker { - private: - template - struct GetSolutionType { - using type = T; - }; - - template<> - struct GetSolutionType { - using type = double; - }; - - template<> - struct GetSolutionType { - using type = storm::RationalNumber; - }; + private: + // Due to a GCC bug we have to add this dummy template type here + // https://stackoverflow.com/questions/49707184/explicit-specialization-in-non-namespace-scope-does-not-compile-in-gcc + template + struct GetSolutionType { + using type = T; + }; + + template + struct GetSolutionType { + using type = double; + }; + + template + struct GetSolutionType { + using type = storm::RationalNumber; + }; + public: typedef typename SparseModelType::ValueType ValueType; typedef typename SparseModelType::RewardModelType RewardModelType; - using SolutionType = typename GetSolutionType::type; + using SolutionType = typename GetSolutionType::type; explicit SparsePropositionalModelChecker(SparseModelType const& model); From 65251a52668053e93c95f0679b8cb400b8fed5fa Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Fri, 4 Jul 2025 23:21:31 +0200 Subject: [PATCH 028/102] polish conditional implementation --- .../modelchecker/ModelCheckerEnvironment.cpp | 10 + .../modelchecker/ModelCheckerEnvironment.h | 5 + .../conditional/ConditionalAlgorithm.cpp | 36 ++++ .../helper/conditional/ConditionalAlgorithm.h | 13 ++ .../helper/conditional/ConditionalHelper.cpp | 196 +++++++++++------- .../prctl/helper/SparseMdpPrctlHelper.cpp | 173 ---------------- .../prctl/helper/SparseMdpPrctlHelper.h | 8 +- .../settings/modules/ModelCheckerSettings.cpp | 28 ++- .../settings/modules/ModelCheckerSettings.h | 13 +- 9 files changed, 214 insertions(+), 268 deletions(-) create mode 100644 src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.cpp create mode 100644 src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp index 829232468f..f88e3849c1 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp @@ -19,6 +19,8 @@ ModelCheckerEnvironment::ModelCheckerEnvironment() { } auto const& ioSettings = storm::settings::getModule(); steadyStateDistributionAlgorithm = ioSettings.getSteadyStateDistributionAlgorithm(); + + conditionalAlgorithm = mcSettings.getConditionalAlgorithm(); } ModelCheckerEnvironment::~ModelCheckerEnvironment() { @@ -33,6 +35,14 @@ void ModelCheckerEnvironment::setSteadyStateDistributionAlgorithm(SteadyStateDis steadyStateDistributionAlgorithm = value; } +ConditionalAlgorithm ModelCheckerEnvironment::getConditionalAlgorithm() const { + return conditionalAlgorithm; +} + +void ModelCheckerEnvironment::setConditionalAlgorithm(ConditionalAlgorithm value) { + conditionalAlgorithm = value; +} + MultiObjectiveModelCheckerEnvironment& ModelCheckerEnvironment::multi() { return multiObjectiveModelCheckerEnvironment.get(); } diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h index a98678dc6c..162add631f 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h @@ -6,6 +6,7 @@ #include "storm/environment/Environment.h" #include "storm/environment/SubEnvironment.h" +#include "storm/modelchecker/helper/conditional/ConditionalAlgorithm.h" #include "storm/modelchecker/helper/infinitehorizon/SteadyStateDistributionAlgorithm.h" namespace storm { @@ -24,6 +25,9 @@ class ModelCheckerEnvironment { SteadyStateDistributionAlgorithm getSteadyStateDistributionAlgorithm() const; void setSteadyStateDistributionAlgorithm(SteadyStateDistributionAlgorithm value); + ConditionalAlgorithm getConditionalAlgorithm() const; + void setConditionalAlgorithm(ConditionalAlgorithm value); + bool isLtl2daToolSet() const; std::string const& getLtl2daTool() const; void setLtl2daTool(std::string const& value); @@ -33,5 +37,6 @@ class ModelCheckerEnvironment { SubEnvironment multiObjectiveModelCheckerEnvironment; boost::optional ltl2daTool; SteadyStateDistributionAlgorithm steadyStateDistributionAlgorithm; + ConditionalAlgorithm conditionalAlgorithm; }; } // namespace storm diff --git a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.cpp b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.cpp new file mode 100644 index 0000000000..ba494fb4e9 --- /dev/null +++ b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.cpp @@ -0,0 +1,36 @@ +#include "ConditionalAlgorithm.h" + +namespace storm { +std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithm const& algorithm) { + switch (algorithm) { + case ConditionalAlgorithm::Default: + return stream << "default"; + case ConditionalAlgorithm::Restart: + return stream << "restart"; + case ConditionalAlgorithm::Bisection: + return stream << "bisection"; + case ConditionalAlgorithm::BisectionAdvanced: + return stream << "bisection-advanced"; + case ConditionalAlgorithm::PolicyIteration: + return stream << "pi"; + } + STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unknown conditional algorithm"); + return stream; +} + +ConditionalAlgorithm conditionalAlgorithmFromString(std::string const& algorithm) { + if (algorithm == "default") { + return ConditionalAlgorithm::Default; + } else if (algorithm == "restart") { + return ConditionalAlgorithm::Restart; + } else if (algorithm == "bisection") { + return ConditionalAlgorithm::Bisection; + } else if (algorithm == "bisection-advanced") { + return ConditionalAlgorithm::BisectionAdvanced; + } else if (algorithm == "pi") { + return ConditionalAlgorithm::PolicyIteration; + } + STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unknown conditional algorithm: " << algorithm); +} + +} // namespace storm \ No newline at end of file diff --git a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h new file mode 100644 index 0000000000..d24b8bbdb8 --- /dev/null +++ b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h @@ -0,0 +1,13 @@ +#pragma once +#include + +#include "storm/exceptions/UnexpectedException.h" +#include "storm/utility/macros.h" + +namespace storm { +enum class ConditionalAlgorithm { Default, Restart, Bisection, BisectionAdvanced, PolicyIteration }; + +std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithm const& algorithm); +ConditionalAlgorithm conditionalAlgorithmFromString(std::string const& algorithm); + +} // namespace storm \ No newline at end of file diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 57de83d07d..5032944e27 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -4,6 +4,7 @@ #include "storm/modelchecker/helper/conditional/ConditionalHelper.h" #include "storm/adapters/RationalNumberAdapter.h" +#include "storm/environment/modelchecker/ModelCheckerEnvironment.h" #include "storm/environment/solver/MinMaxSolverEnvironment.h" #include "storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" @@ -13,16 +14,14 @@ #include "storm/storage/SparseMatrix.h" #include "storm/transformer/EndComponentEliminator.h" #include "storm/utility/Extremum.h" -#include "storm/utility/Stopwatch.h" +#include "storm/utility/KwekMehlhorn.h" +#include "storm/utility/SignalHandler.h" #include "storm/utility/graph.h" #include "storm/utility/macros.h" #include "storm/exceptions/NotImplementedException.h" #include "storm/exceptions/NotSupportedException.h" -#include "storm/settings/SettingsManager.h" -#include "storm/settings/modules/ModelCheckerSettings.h" - namespace storm::modelchecker { namespace internal { @@ -107,7 +106,7 @@ SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::sto /*! * Computes the reachability probabilities for the given target states and inserts all non-zero values into the given map. - * The assumption is that usually, not all states are reachable from the initial states. + * @note This code is optimized for cases where not all states are reachable from the initial states. */ template void computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, @@ -124,7 +123,6 @@ void computeReachabilityProbabilities(Environment const& env, std::map::computeUntilProbabilities( env, storm::solver::SolveGoal(dir, subInits), submatrix, submatrix.transpose(true), storm::storage::BitVector(subTargets.size(), true), subTargets, false, false); @@ -299,17 +297,22 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init selectedStatesInMatrix.set(initStateInMatrix, true); eliminateEndComponents(selectedStatesInMatrix, false, std::nullopt, matrix, initStateInMatrix, rowsWithSum1, rowValues); - STORM_PRINT_AND_LOG("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " - << matrix.getEntryCount() << " transitions.\n"); + STORM_LOG_INFO("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " + << matrix.getEntryCount() << " transitions.\n"); // Finally, solve the equation system return solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); } +/*! + * A helper class that computes (weighted) reachability probabilities for a given MDP in normal form. + * @tparam ValueType + * @tparam SolutionType + */ template -class WeightedDiffComputer { +class WeightedReachabilityHelper { public: - WeightedDiffComputer(uint64_t const initialState, storm::storage::SparseMatrix const& transitionMatrix, - NormalFormData const& normalForm) { + WeightedReachabilityHelper(uint64_t const initialState, storm::storage::SparseMatrix const& transitionMatrix, + NormalFormData const& normalForm) { // Determine rowgroups (states) and rows (choices) of the submatrix auto subMatrixRowGroups = normalForm.maybeStates; // Identify and eliminate the initial component to enforce that it is eventually exited @@ -418,20 +421,14 @@ class WeightedDiffComputer { } submatrix = matrixBuilder.build(); - // std::cout << "Submatrix before ec elim:\n" << submatrix << std::endl; - // std::cout << "targetRowValues before ec elim:\n" << storm::utility::vector::toString(targetRowValues) << std::endl; - // std::cout << "conditionRowValues before ec elim:\n" << storm::utility::vector::toString(conditionRowValues) << std::endl; // eliminate ECs if present. We already checked that the initial state can not yield observation failure, so it cannot be part of an EC. // For all remaining ECs, staying in an EC forever is reflected by collecting a value of zero for both, target and condition storm::storage::BitVector allExceptInit(numSubmatrixRowGroups, true); allExceptInit.set(initialStateInSubmatrix, false); eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, conditionRowValues); - // std::cout << "Submatrix after ec elim:\n" << submatrix << std::endl; - // std::cout << "targetRowValues after ec elim:\n" << storm::utility::vector::toString(targetRowValues) << std::endl; - // std::cout << "conditionRowValues after ec elim:\n" << storm::utility::vector::toString(conditionRowValues) << std::endl; - STORM_PRINT_AND_LOG("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " - << submatrix.getEntryCount() << " transitions.\n"); + STORM_LOG_INFO("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " + << submatrix.getEntryCount() << " transitions.\n"); } SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, @@ -450,8 +447,6 @@ class WeightedDiffComputer { solver->setLowerBound(-storm::utility::one()); solver->setUpperBound(storm::utility::one()); - // std::cout << "solving equation system with matrix \n" << submatrix << " and row values \n" << storm::utility::vector::toString(rowValues) << - // std::endl; Solve the corresponding system of equations. solver->solveEquations(env, x, rowValues); return x[initialStateInSubmatrix]; } @@ -542,25 +537,45 @@ template SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds boundOption, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { - SolutionType const precision = storm::utility::convertNumber(env.solver().minMax().getPrecision()); + // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper + STORM_LOG_WARN_COND(!env.solver().isForceSoundness(), + "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); + SolutionType const precision = [&env, boundOption]() { + if (storm::NumberTraits::IsExact && env.solver().isForceExact()) { + STORM_LOG_WARN_COND(storm::NumberTraits::IsExact && boundOption == BisectionMethodBounds::Advanced, + "Selected bisection method with exact precision in a setting that might not terminate."); + return storm::utility::zero(); + } else { + return storm::utility::convertNumber(env.solver().minMax().getPrecision()); + } + }(); bool const relative = env.solver().minMax().getRelativeTerminationCriterion(); - WeightedDiffComputer wdc(initialState, transitionMatrix, normalForm); + WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm); SolutionType pMin{storm::utility::zero()}; SolutionType pMax{storm::utility::one()}; + if (boundOption == BisectionMethodBounds::Advanced) { - pMin = wdc.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); - pMax = wdc.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); - STORM_LOG_INFO("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) - << ",\n\t Upper bound: " << storm::utility::convertNumber(pMax) << "\n\n"); + pMin = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); + pMax = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); + STORM_LOG_TRACE("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) + << ",\n\t Upper bound: " << storm::utility::convertNumber(pMax)); } storm::utility::Extremum lowerBound = storm::utility::zero(); storm::utility::Extremum upperBound = storm::utility::one(); - storm::Environment absEnv = env; - absEnv.solver().minMax().setRelativeTerminationCriterion(false); + SolutionType middle = (*lowerBound + *upperBound) / 2; for (uint64_t iterationCount = 1; true; ++iterationCount) { - SolutionType const middle = (*lowerBound + *upperBound) / 2; - SolutionType const middleValue = wdc.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + if constexpr (storm::NumberTraits::IsExact) { + // find a rational number with a concise representation close to middle and within the bounds + auto const exactMiddle = middle; + auto numDigits = storm::utility::convertNumber( + storm::utility::floor(storm::utility::log10(storm::utility::one() / (*upperBound - *lowerBound)))); + do { + ++numDigits; + middle = storm::utility::kwek_mehlhorn::sharpen(numDigits, exactMiddle); + } while (middle <= *lowerBound || middle >= *upperBound); + } + SolutionType const middleValue = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle); if (boundOption == BisectionMethodBounds::Simple) { if (middleValue >= storm::utility::zero()) { lowerBound &= middle; @@ -568,6 +583,7 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b if (middleValue <= storm::utility::zero()) { upperBound &= middle; } + middle = (*lowerBound + *upperBound) / 2; // update middle to the average of the bounds } else { STORM_LOG_ASSERT(boundOption == BisectionMethodBounds::Advanced, "Unknown bisection method bounds"); if (middleValue >= storm::utility::zero()) { @@ -578,19 +594,23 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b lowerBound &= middle + (middleValue / pMin); upperBound &= middle + (middleValue / pMax); } + // update middle to the average of the bounds, but scale it according to the middle value (which is in [-1,1]) + middle = *lowerBound + (1 + middleValue) * (*upperBound - *lowerBound) / 2; } SolutionType const boundDiff = *upperBound - *lowerBound; - STORM_LOG_INFO("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) - << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) - << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) - << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "\n\n"); + STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) + << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) + << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) + << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "\n\n"); if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { - STORM_PRINT_AND_LOG("Bisection method converged after " << iterationCount << " iterations.\n"); - STORM_PRINT_AND_LOG("Difference is " << std::setprecision(std::numeric_limits::digits10) << storm::utility::convertNumber(boundDiff) - << ".\n"); - if (std::is_same_v && storm::utility::isZero(boundDiff)) { - STORM_PRINT_AND_LOG("Result is exact."); - } + STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " + << std::setprecision(std::numeric_limits::digits10) + << storm::utility::convertNumber(boundDiff) << ".\n"); + break; + } + if (storm::utility::resources::isTerminate()) { + STORM_LOG_WARN("Bisection solver aborted after " << iterationCount << "iterations. Bound difference is " + << storm::utility::convertNumber(boundDiff) << ".\n"); break; } } @@ -600,25 +620,33 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b template SolutionType computeViaPolicyIteration(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { - WeightedDiffComputer wdc(initialState, transitionMatrix, normalForm); + WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm); std::vector scheduler; std::vector targetResults, conditionResults; for (uint64_t iterationCount = 1; true; ++iterationCount) { - wdc.evaluateScheduler(env, scheduler, targetResults, conditionResults); - STORM_LOG_ASSERT(targetResults[wdc.getInternalInitialState()] <= conditionResults[wdc.getInternalInitialState()], - "Target value must be less or equal than condition value"); // todo: floats?? - ValueType const lambda = storm::utility::isZero(conditionResults[wdc.getInternalInitialState()]) + wrh.evaluateScheduler(env, scheduler, targetResults, conditionResults); + STORM_LOG_WARN_COND( + targetResults[wrh.getInternalInitialState()] <= conditionResults[wrh.getInternalInitialState()], + "Potential numerical issues: the probability to reach the target is greater than the probability to reach the condition. Difference is " + << (storm::utility::convertNumber(targetResults[wrh.getInternalInitialState()] - + conditionResults[wrh.getInternalInitialState()])) + << "."); + ValueType const lambda = storm::utility::isZero(conditionResults[wrh.getInternalInitialState()]) ? storm::utility::zero() - : ValueType(targetResults[wdc.getInternalInitialState()] / conditionResults[wdc.getInternalInitialState()]); + : ValueType(targetResults[wrh.getInternalInitialState()] / conditionResults[wrh.getInternalInitialState()]); bool schedulerChanged{false}; if (storm::solver::minimize(dir)) { - schedulerChanged = wdc.template improveScheduler(scheduler, lambda, targetResults, conditionResults); + schedulerChanged = wrh.template improveScheduler(scheduler, lambda, targetResults, conditionResults); } else { - schedulerChanged = wdc.template improveScheduler(scheduler, lambda, targetResults, conditionResults); + schedulerChanged = wrh.template improveScheduler(scheduler, lambda, targetResults, conditionResults); } if (!schedulerChanged) { - STORM_PRINT_AND_LOG("Policy iteration converged after " << iterationCount << " iterations.\n"); + STORM_LOG_INFO("Policy iteration for conditional probabilities converged after " << iterationCount << " iterations.\n"); + return lambda; + } + if (storm::utility::resources::isTerminate()) { + STORM_LOG_WARN("Policy iteration for conditional probabilities converged aborted after " << iterationCount << "iterations."); return lambda; } } @@ -631,18 +659,29 @@ std::unique_ptr computeConditionalProbabilities(Environment const& storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { + // We might require adapting the precision of the solver to counter error propagation (e.g. when computing the normal form). + auto normalFormConstructionEnv = env; + auto analysisEnv = env; + if (env.solver().isForceSoundness()) { + normalFormConstructionEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * + storm::utility::convertNumber("1/10")); + analysisEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * + storm::utility::convertNumber("9/10")); + } + // We first translate the problem into a normal form. // @see doi.org/10.1007/978-3-642-54862-8_43 STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, "Only one initial state is supported for conditional probabilities"); - STORM_PRINT_AND_LOG("Computing conditional probabilities for a model with " << transitionMatrix.getRowGroupCount() << " states and " - << transitionMatrix.getEntryCount() << " transitions.\n"); - storm::utility::Stopwatch sw(true); - auto normalFormData = - internal::obtainNormalForm(env, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), targetStates, conditionStates); - sw.stop(); - STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); + STORM_LOG_TRACE("Computing conditional probabilities for a model with " << transitionMatrix.getRowGroupCount() << " states and " + << transitionMatrix.getEntryCount() << " transitions.\n"); + // storm::utility::Stopwatch sw(true); + auto normalFormData = internal::obtainNormalForm(normalFormConstructionEnv, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), + targetStates, conditionStates); + // sw.stop(); + // STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); // Then, we solve the induced problem using the selected algorithm + STORM_LOG_ASSERT(goal.relevantValues().getNumberOfSetBits() == 1, "Only one initial state is supported for conditional probabilities"); auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); if (normalFormData.terminalStates.get(initialState)) { @@ -655,26 +694,35 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // In this case, all schedulers induce a conditional probability of 1 (or do not reach the condition, i.e., have undefined value) initialStateValue = storm::utility::one(); } - STORM_PRINT_AND_LOG("Initial state is terminal.\n"); + STORM_LOG_INFO("Initial state is terminal.\n"); } else { STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState), "Initial state must be a maybe state if it is not a terminal state"); - auto const algString = storm::settings::getModule().getConditionalAlgorithm(); - STORM_PRINT_AND_LOG("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << algString - << "'.\n"); - sw.restart(); - if (algString == "restart" || algString == "default") { - initialStateValue = internal::computeViaRestartMethod(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); - } else if (algString == "bisection" || algString == "bisection-advanced") { - auto const boundOption = (algString == "bisection" ? internal::BisectionMethodBounds::Simple : internal::BisectionMethodBounds::Advanced); - initialStateValue = - internal::computeViaBisection(env, boundOption, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); - } else if (algString == "pi") { - initialStateValue = internal::computeViaPolicyIteration(env, *goal.relevantValues().begin(), goal.direction(), transitionMatrix, normalFormData); - } else { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " + algString); + auto alg = analysisEnv.modelchecker().getConditionalAlgorithm(); + if (alg == ConditionalAlgorithm::Default) { + alg = ConditionalAlgorithm::Restart; + } + STORM_LOG_INFO("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg << "."); + // sw.restart(); + switch (alg) { + case ConditionalAlgorithm::Restart: + initialStateValue = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); + break; + case ConditionalAlgorithm::Bisection: + initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal.direction(), + transitionMatrix, normalFormData); + break; + case ConditionalAlgorithm::BisectionAdvanced: + initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal.direction(), + transitionMatrix, normalFormData); + break; + case ConditionalAlgorithm::PolicyIteration: + initialStateValue = internal::computeViaPolicyIteration(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); + break; + default: + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " << alg); } - sw.stop(); - STORM_PRINT_AND_LOG("Time for analyzing the normal form: " << sw << ".\n"); + // sw.stop(); + // STORM_PRINT_AND_LOG("Time for analyzing the normal form: " << sw << ".\n"); } return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); } diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 064a9cc785..815ee2805d 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -1438,179 +1438,6 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper -std::unique_ptr SparseMdpPrctlHelper::computeConditionalProbabilities( - Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, - storm::storage::BitVector const& conditionStates) { - if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional probabilities with interval models."); - } else { - std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); - - // For the max-case, we can simply take the given target states. For the min-case, however, we need to - // find the MECs of non-target states and make them the new target states. - storm::storage::BitVector fixedTargetStates; - if (!goal.minimize()) { - fixedTargetStates = targetStates; - } else { - fixedTargetStates = storm::storage::BitVector(targetStates.size()); - storm::storage::MaximalEndComponentDecomposition mecDecomposition(transitionMatrix, backwardTransitions, ~targetStates); - for (auto const& mec : mecDecomposition) { - for (auto const& stateActionsPair : mec) { - fixedTargetStates.set(stateActionsPair.first); - } - } - } - - storm::storage::BitVector allStates(fixedTargetStates.size(), true); - - // Extend the target states by computing all states that have probability 1 to go to a target state - // under *all* schedulers. - fixedTargetStates = - storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, fixedTargetStates); - - // We solve the max-case and later adjust the result if the optimization direction was to minimize. - storm::storage::BitVector initialStatesBitVector = goal.relevantValues(); - STORM_LOG_THROW(initialStatesBitVector.getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, - "Computing conditional probabilities in MDPs is only supported for models with exactly one initial state."); - storm::storage::sparse::state_type initialState = *initialStatesBitVector.begin(); - - // Extend the condition states by computing all states that have probability 1 to go to a condition state - // under *all* schedulers. - storm::storage::BitVector extendedConditionStates = - storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); - - STORM_LOG_DEBUG("Computing probabilities to satisfy condition."); - std::chrono::high_resolution_clock::time_point conditionStart = std::chrono::high_resolution_clock::now(); - std::vector conditionProbabilities = - std::move(computeUntilProbabilities(env, OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, extendedConditionStates, - false, false) - .values); - std::chrono::high_resolution_clock::time_point conditionEnd = std::chrono::high_resolution_clock::now(); - STORM_LOG_DEBUG("Computed probabilities to satisfy for condition in " - << std::chrono::duration_cast(conditionEnd - conditionStart).count() << "ms."); - - // If the conditional probability is undefined for the initial state, we return directly. - if (storm::utility::isZero(conditionProbabilities[initialState])) { - return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, storm::utility::infinity())); - } - - STORM_LOG_DEBUG("Computing probabilities to reach target."); - std::chrono::high_resolution_clock::time_point targetStart = std::chrono::high_resolution_clock::now(); - std::vector targetProbabilities = std::move( - computeUntilProbabilities(env, OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, fixedTargetStates, false, false) - .values); - std::chrono::high_resolution_clock::time_point targetEnd = std::chrono::high_resolution_clock::now(); - STORM_LOG_DEBUG("Computed probabilities to reach target in " << std::chrono::duration_cast(targetEnd - targetStart).count() - << "ms."); - - storm::storage::BitVector statesWithProbabilityGreater0E(transitionMatrix.getRowGroupCount(), true); - storm::storage::sparse::state_type state = 0; - for (auto const& element : conditionProbabilities) { - if (storm::utility::isZero(element)) { - statesWithProbabilityGreater0E.set(state, false); - } - ++state; - } - - // Determine those states that need to be equipped with a restart mechanism. - STORM_LOG_DEBUG("Computing problematic states."); - storm::storage::BitVector pureResetStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); - storm::storage::BitVector problematicStates = storm::utility::graph::performProb0E( - transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, extendedConditionStates | fixedTargetStates); - - // Otherwise, we build the transformed MDP. - storm::storage::BitVector relevantStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStatesBitVector, allStates, - extendedConditionStates | fixedTargetStates | pureResetStates); - STORM_LOG_TRACE("Found " << relevantStates.getNumberOfSetBits() << " relevant states for conditional probability computation."); - std::vector numberOfStatesBeforeRelevantStates = relevantStates.getNumberOfSetBitsBeforeIndices(); - storm::storage::sparse::state_type newGoalState = relevantStates.getNumberOfSetBits(); - storm::storage::sparse::state_type newStopState = newGoalState + 1; - storm::storage::sparse::state_type newFailState = newStopState + 1; - - // Build the transitions of the (relevant) states of the original model. - storm::storage::SparseMatrixBuilder builder(0, newFailState + 1, 0, true, true); - uint_fast64_t currentRow = 0; - for (auto state : relevantStates) { - builder.newRowGroup(currentRow); - if (fixedTargetStates.get(state)) { - if (!storm::utility::isZero(conditionProbabilities[state])) { - builder.addNextValue(currentRow, newGoalState, conditionProbabilities[state]); - } - if (!storm::utility::isOne(conditionProbabilities[state])) { - builder.addNextValue(currentRow, newFailState, storm::utility::one() - conditionProbabilities[state]); - } - ++currentRow; - } else if (extendedConditionStates.get(state)) { - if (!storm::utility::isZero(targetProbabilities[state])) { - builder.addNextValue(currentRow, newGoalState, targetProbabilities[state]); - } - if (!storm::utility::isOne(targetProbabilities[state])) { - builder.addNextValue(currentRow, newStopState, storm::utility::one() - targetProbabilities[state]); - } - ++currentRow; - } else if (pureResetStates.get(state)) { - builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one()); - ++currentRow; - } else { - for (uint_fast64_t row = transitionMatrix.getRowGroupIndices()[state]; row < transitionMatrix.getRowGroupIndices()[state + 1]; ++row) { - for (auto const& successorEntry : transitionMatrix.getRow(row)) { - builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[successorEntry.getColumn()], successorEntry.getValue()); - } - ++currentRow; - } - if (problematicStates.get(state)) { - builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one()); - ++currentRow; - } - } - } - - // Now build the transitions of the newly introduced states. - builder.newRowGroup(currentRow); - builder.addNextValue(currentRow, newGoalState, storm::utility::one()); - ++currentRow; - builder.newRowGroup(currentRow); - builder.addNextValue(currentRow, newStopState, storm::utility::one()); - ++currentRow; - builder.newRowGroup(currentRow); - builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one()); - ++currentRow; - - std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); - STORM_LOG_DEBUG("Computed transformed model in " << std::chrono::duration_cast(end - start).count() << "ms."); - - // Finally, build the matrix and dispatch the query as a reachability query. - STORM_LOG_DEBUG("Computing conditional probabilties."); - storm::storage::BitVector newGoalStates(newFailState + 1); - newGoalStates.set(newGoalState); - storm::storage::SparseMatrix newTransitionMatrix = builder.build(); - STORM_LOG_DEBUG("Transformed model has " << newTransitionMatrix.getRowGroupCount() << " states and " << newTransitionMatrix.getNonzeroEntryCount() - << " transitions."); - storm::storage::SparseMatrix newBackwardTransitions = newTransitionMatrix.transpose(true); - - storm::solver::OptimizationDirection dir = goal.direction(); - if (goal.minimize()) { - goal.oneMinus(); - } - - std::chrono::high_resolution_clock::time_point conditionalStart = std::chrono::high_resolution_clock::now(); - std::vector goalProbabilities = - std::move(computeUntilProbabilities(env, std::move(goal), newTransitionMatrix, newBackwardTransitions, - storm::storage::BitVector(newFailState + 1, true), newGoalStates, false, false) - .values); - std::chrono::high_resolution_clock::time_point conditionalEnd = std::chrono::high_resolution_clock::now(); - STORM_LOG_DEBUG("Computed conditional probabilities in transformed model in " - << std::chrono::duration_cast(conditionalEnd - conditionalStart).count() << "ms."); - - return std::unique_ptr(new ExplicitQuantitativeCheckResult( - initialState, dir == OptimizationDirection::Maximize - ? goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]] - : storm::utility::one() - goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]])); - } -} - template class SparseMdpPrctlHelper; template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h index 5510b92c13..30bde72e64 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h @@ -91,13 +91,7 @@ class SparseMdpPrctlHelper { storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative); - - static std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, - storm::storage::BitVector const& targetStates, - storm::storage::BitVector const& conditionStates); - + private: static MDPSparseModelCheckingHelperReturnType computeReachabilityRewardsHelper( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index bb5060ea09..0c0e123e93 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -7,9 +7,10 @@ #include "storm/settings/SettingMemento.h" #include "storm/settings/SettingsManager.h" -namespace storm { -namespace settings { -namespace modules { +#include "storm/exceptions/NotImplementedException.h" +#include "storm/utility/macros.h" + +namespace storm::settings::modules { const std::string ModelCheckerSettings::moduleName = "modelchecker"; const std::string ModelCheckerSettings::filterRewZeroOptionName = "filterrewzero"; @@ -28,9 +29,14 @@ ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { "filename", "A script that can be called with a prefix formula and a name for the output automaton.") .build()) .build()); + + std::vector const conditionalAlgs = {"default", "restart", "bisection", "bisection-advanced", "pi"}; this->addOption(storm::settings::OptionBuilder(moduleName, conditionalAlgorithmOptionName, false, "The used algorithm for conditional probabilities.") .setIsAdvanced() - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("alg", "name.").build()) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the method to use.") + .addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(conditionalAlgs)) + .setDefaultValueString("default") + .build()) .build()); } @@ -46,12 +52,12 @@ std::string ModelCheckerSettings::getLtl2daTool() const { return this->getOption(ltl2daToolOptionName).getArgumentByName("filename").getValueAsString(); } -std::string ModelCheckerSettings::getConditionalAlgorithm() const { // TODO - return this->getOption(conditionalAlgorithmOptionName).getHasOptionBeenSet() - ? this->getOption(conditionalAlgorithmOptionName).getArgumentByName("alg").getValueAsString() - : "default"; +bool ModelCheckerSettings::isConditionalAlgorithmSet() const { + return this->getOption(conditionalAlgorithmOptionName).getHasOptionBeenSet(); +} + +ConditionalAlgorithm ModelCheckerSettings::getConditionalAlgorithm() const { + return conditionalAlgorithmFromString(this->getOption(conditionalAlgorithmOptionName).getArgumentByName("name").getValueAsString()); } -} // namespace modules -} // namespace settings -} // namespace storm +} // namespace storm::settings::modules diff --git a/src/storm/settings/modules/ModelCheckerSettings.h b/src/storm/settings/modules/ModelCheckerSettings.h index 3ffb7a6eb4..6643236b64 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.h +++ b/src/storm/settings/modules/ModelCheckerSettings.h @@ -1,10 +1,9 @@ #pragma once #include "storm-config.h" +#include "storm/modelchecker/helper/conditional/ConditionalAlgorithm.h" #include "storm/settings/modules/ModuleSettings.h" -#include "storm/builder/ExplorationOrder.h" - namespace storm { namespace settings { namespace modules { @@ -35,7 +34,15 @@ class ModelCheckerSettings : public ModuleSettings { */ std::string getLtl2daTool() const; - std::string getConditionalAlgorithm() const; // TODO: do this properly + /*! + * Retrieves whether an algorithm for conditional properties has been set. + */ + bool isConditionalAlgorithmSet() const; + + /*! + * Retrieves the specified algorithm for conditional probabilities. + */ + ConditionalAlgorithm getConditionalAlgorithm() const; // The name of the module. static const std::string moduleName; From 5b248b0e6428167608166d53fc5c9b86ab943caa Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sat, 5 Jul 2025 09:42:02 +0200 Subject: [PATCH 029/102] Further polishing conditional probabilities --- .../helper/conditional/ConditionalHelper.cpp | 90 ++++++++++++------- .../prctl/SparseMdpPrctlModelChecker.cpp | 2 + 2 files changed, 62 insertions(+), 30 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 5032944e27..f70a4dc843 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -298,7 +298,7 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init eliminateEndComponents(selectedStatesInMatrix, false, std::nullopt, matrix, initStateInMatrix, rowsWithSum1, rowValues); STORM_LOG_INFO("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " - << matrix.getEntryCount() << " transitions.\n"); + << matrix.getEntryCount() << " transitions."); // Finally, solve the equation system return solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); } @@ -428,7 +428,7 @@ class WeightedReachabilityHelper { eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, conditionRowValues); STORM_LOG_INFO("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " - << submatrix.getEntryCount() << " transitions.\n"); + << submatrix.getEntryCount() << " transitions."); } SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, @@ -541,7 +541,7 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b STORM_LOG_WARN_COND(!env.solver().isForceSoundness(), "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); SolutionType const precision = [&env, boundOption]() { - if (storm::NumberTraits::IsExact && env.solver().isForceExact()) { + if (storm::NumberTraits::IsExact || env.solver().isForceExact()) { STORM_LOG_WARN_COND(storm::NumberTraits::IsExact && boundOption == BisectionMethodBounds::Advanced, "Selected bisection method with exact precision in a setting that might not terminate."); return storm::utility::zero(); @@ -565,17 +565,9 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b storm::utility::Extremum upperBound = storm::utility::one(); SolutionType middle = (*lowerBound + *upperBound) / 2; for (uint64_t iterationCount = 1; true; ++iterationCount) { - if constexpr (storm::NumberTraits::IsExact) { - // find a rational number with a concise representation close to middle and within the bounds - auto const exactMiddle = middle; - auto numDigits = storm::utility::convertNumber( - storm::utility::floor(storm::utility::log10(storm::utility::one() / (*upperBound - *lowerBound)))); - do { - ++numDigits; - middle = storm::utility::kwek_mehlhorn::sharpen(numDigits, exactMiddle); - } while (middle <= *lowerBound || middle >= *upperBound); - } + // evaluate the current middle SolutionType const middleValue = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + // update the bounds and new middle value according to the bisection method if (boundOption == BisectionMethodBounds::Simple) { if (middleValue >= storm::utility::zero()) { lowerBound &= middle; @@ -595,24 +587,46 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b upperBound &= middle + (middleValue / pMax); } // update middle to the average of the bounds, but scale it according to the middle value (which is in [-1,1]) - middle = *lowerBound + (1 + middleValue) * (*upperBound - *lowerBound) / 2; + middle = *lowerBound + (storm::utility::one() + middleValue) * (*upperBound - *lowerBound) / 2; + STORM_LOG_ASSERT(middle >= *lowerBound && middle <= *upperBound, "Bisection method bounds are inconsistent."); } + // check for convergence SolutionType const boundDiff = *upperBound - *lowerBound; STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) - << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "\n\n"); + << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "."); if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " << std::setprecision(std::numeric_limits::digits10) - << storm::utility::convertNumber(boundDiff) << ".\n"); + << storm::utility::convertNumber(boundDiff) << "."); break; } + // check for early termination if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Bisection solver aborted after " << iterationCount << "iterations. Bound difference is " - << storm::utility::convertNumber(boundDiff) << ".\n"); + << storm::utility::convertNumber(boundDiff) << "."); break; } + // process the middle value for the next iteration + if constexpr (storm::NumberTraits::IsExact) { + // find a rational number with a concise representation close to middle and within the bounds + auto const exactMiddle = middle; + auto numDigits = storm::utility::convertNumber( + storm::utility::floor(storm::utility::log10(storm::utility::one() / (*upperBound - *lowerBound)))); + do { + ++numDigits; + middle = storm::utility::kwek_mehlhorn::sharpen(numDigits, exactMiddle); + } while (middle <= *lowerBound || middle >= *upperBound); + } + // Since above code never sets 'middle' to exactly zero or one, we check if that could be necessary after a couple of iterations + if (iterationCount == 8) { // 8 is just a heuristic value, it could be any number + if (storm::utility::isZero(*lowerBound)) { + middle = storm::utility::zero(); + } else if (storm::utility::isOne(*upperBound)) { + middle = storm::utility::one(); + } + } } return (*lowerBound + *upperBound) / 2; } @@ -642,7 +656,7 @@ SolutionType computeViaPolicyIteration(Environment const& env, uint64_t const in schedulerChanged = wrh.template improveScheduler(scheduler, lambda, targetResults, conditionResults); } if (!schedulerChanged) { - STORM_LOG_INFO("Policy iteration for conditional probabilities converged after " << iterationCount << " iterations.\n"); + STORM_LOG_INFO("Policy iteration for conditional probabilities converged after " << iterationCount << " iterations."); return lambda; } if (storm::utility::resources::isTerminate()) { @@ -652,6 +666,28 @@ SolutionType computeViaPolicyIteration(Environment const& env, uint64_t const in } } +template +std::optional handleTrivialCases(uint64_t const initialState, NormalFormData const& normalForm) { + if (normalForm.terminalStates.get(initialState)) { + STORM_LOG_DEBUG("Initial state is terminal."); + if (normalForm.conditionStates.get(initialState)) { + return normalForm.targetValue(initialState); // The value is already known, nothing to do. + } else { + STORM_LOG_THROW(!normalForm.universalObservationFailureStates.get(initialState), storm::exceptions::NotSupportedException, + "Trying to compute undefined conditional probability: the condition has probability 0 under all policies."); + // The last case for a terminal initial state is that it is already target and the condition is reachable with non-zero probability. + // In this case, all schedulers induce a conditional probability of 1 (or do not reach the condition, i.e., have undefined value) + return storm::utility::one(); + } + } else { + // Catch the case where all terminal states have value zero + if (normalForm.nonZeroTargetStateValues.empty()) { + return storm::utility::zero(); + }; + } + return std::nullopt; // No trivial case applies, we need to compute the value. +} + } // namespace internal template @@ -671,10 +707,12 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // We first translate the problem into a normal form. // @see doi.org/10.1007/978-3-642-54862-8_43 + STORM_LOG_THROW(goal.hasRelevantValues(), storm::exceptions::NotSupportedException, + "No initial state given. Conditional probabilities can only be computed for models with a single initial state."); STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, "Only one initial state is supported for conditional probabilities"); STORM_LOG_TRACE("Computing conditional probabilities for a model with " << transitionMatrix.getRowGroupCount() << " states and " - << transitionMatrix.getEntryCount() << " transitions.\n"); + << transitionMatrix.getEntryCount() << " transitions."); // storm::utility::Stopwatch sw(true); auto normalFormData = internal::obtainNormalForm(normalFormConstructionEnv, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), targetStates, conditionStates); @@ -684,17 +722,9 @@ std::unique_ptr computeConditionalProbabilities(Environment const& STORM_LOG_ASSERT(goal.relevantValues().getNumberOfSetBits() == 1, "Only one initial state is supported for conditional probabilities"); auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); - if (normalFormData.terminalStates.get(initialState)) { - if (normalFormData.conditionStates.get(initialState)) { - initialStateValue = normalFormData.targetValue(initialState); // The value is already known, nothing to do. - } else { - STORM_LOG_THROW(!normalFormData.universalObservationFailureStates.get(initialState), storm::exceptions::NotSupportedException, - "Trying to compute undefined conditional probability: the condition has probability 0 under all policies."); - // The last case for a terminal initial state is that it is already target and the condition is reachable with non-zero probability. - // In this case, all schedulers induce a conditional probability of 1 (or do not reach the condition, i.e., have undefined value) - initialStateValue = storm::utility::one(); - } - STORM_LOG_INFO("Initial state is terminal.\n"); + if (auto trivialValue = internal::handleTrivialCases(initialState, normalFormData); trivialValue.has_value()) { + initialStateValue = *trivialValue; + STORM_LOG_DEBUG("Initial state has trivial value " << initialStateValue); } else { STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState), "Initial state must be a maybe state if it is not a terminal state"); auto alg = analysisEnv.modelchecker().getConditionalAlgorithm(); diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 8441c324bc..dd9c352850 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -265,6 +265,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::InvalidPropertyException, "Cannot compute conditional probabilities on MDPs with more than one initial state."); + STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidPropertyException, + "Conditional probabilities can only be computed for the initial states of the model."); STORM_LOG_THROW(conditionalFormula.getSubformula().isEventuallyFormula(), storm::exceptions::InvalidPropertyException, "Illegal conditional probability formula."); STORM_LOG_THROW(conditionalFormula.getConditionFormula().isEventuallyFormula(), storm::exceptions::InvalidPropertyException, From 43741f0ba357ea2f5cfecea2a099307a9603dc08 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sat, 5 Jul 2025 09:42:18 +0200 Subject: [PATCH 030/102] added a test case for conditional probabilities in mdps --- .../ConditionalMdpPrctlModelCheckerTest.cpp | 274 ++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp diff --git a/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp new file mode 100644 index 0000000000..90aac45102 --- /dev/null +++ b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp @@ -0,0 +1,274 @@ +#include "test/storm_gtest.h" + +#include "storm-config.h" + +#include "storm-parsers/api/properties.h" +#include "storm-parsers/parser/PrismParser.h" +#include "storm/api/builder.h" +#include "storm/api/properties.h" + +#include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h" +#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" + +#include "storm/environment/modelchecker/ModelCheckerEnvironment.h" +#include "storm/environment/solver/MinMaxSolverEnvironment.h" + +namespace { + +class SparseDoubleRestartEnvironment { + public: + static const bool isExact = false; + typedef double ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Restart); + env.solver().minMax().setPrecision(storm::utility::convertNumber(1e-10)); // restart algorithm requires a higher precision + return env; + } +}; + +class SparseDoubleBisectionEnvironment { + public: + static const bool isExact = false; + typedef double ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Bisection); + return env; + } +}; + +class SparseDoubleBisectionAdvancedEnvironment { + public: + static const bool isExact = false; + typedef double ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::BisectionAdvanced); + return env; + } +}; + +class SparseDoublePiEnvironment { + public: + static const bool isExact = false; + typedef double ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::PolicyIteration); + return env; + } +}; + +class SparseRationalNumberRestartEnvironment { + public: + static const bool isExact = true; + typedef storm::RationalNumber ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Restart); + env.solver().minMax().setPrecision(storm::utility::convertNumber(1e-10)); // restart algorithm requires a higher precision + return env; + } +}; + +class SparseRationalNumberBisectionEnvironment { + public: + static const bool isExact = true; + typedef storm::RationalNumber ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Bisection); + return env; + } +}; + +class SparseRationalNumberBisectionAdvancedEnvironment { + public: + static const bool isExact = true; + typedef storm::RationalNumber ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::BisectionAdvanced); + return env; + } +}; + +class SparseRationalNumberPiEnvironment { + public: + static const bool isExact = true; + typedef storm::RationalNumber ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::PolicyIteration); + return env; + } +}; + +template +class ConditionalMdpPrctlModelCheckerTest : public ::testing::Test { + public: + typedef typename TestType::ValueType ValueType; + typedef typename storm::models::sparse::Mdp SparseModelType; + + ConditionalMdpPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {} + + void SetUp() override { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + } + + storm::Environment const& env() const { + return _environment; + } + ValueType parseNumber(std::string const& input) const { + return storm::utility::convertNumber(input); + } + ValueType precision() const { + return TestType::isExact ? parseNumber("0") : parseNumber("1e-6"); + } + bool isSparseModel() const { + return std::is_same::value; + } + + std::pair, std::vector>> buildModelFormulas( + storm::prism::Program const& inputProgram, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const { + std::pair, std::vector>> result; + auto program = storm::utility::prism::preprocess(inputProgram, constantDefinitionString); + result.second = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); + result.first = storm::api::buildSparseModel(program, result.second)->template as(); + return result; + } + + std::vector> getTasks( + std::vector> const& formulas) const { + std::vector> result; + for (auto const& f : formulas) { + result.emplace_back(*f, true); // Set onlyInitialStatesRelevant to true for conditional tasks + } + return result; + } + + private: + storm::Environment _environment; +}; + +typedef ::testing::Types + TestingTypes; + +TYPED_TEST_SUITE(ConditionalMdpPrctlModelCheckerTest, TestingTypes, ); + +TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, two_dice) { + typedef typename TestFixture::ValueType ValueType; + + std::string const formulasString = + "Pmax=? [F \"twelve\" || F d1=6];" + "Pmin=? [F \"twelve\" || F d1=6];" + "Pmax=? [F \"seven\" || F d2=4];" + "Pmin=? [F \"seven\" || F d2=4];" + "Pmax=? [F \"two\" || F d2=2];" + "Pmin=? [F \"two\" || F d2=2];" + "Pmax=? [F d1=6 || F \"twelve\"];" + "Pmin=? [F d1=6 || F \"twelve\"];"; + + auto program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/mdp/two_dice.nm"); + auto modelFormulas = this->buildModelFormulas(program, formulasString); + auto model = std::move(modelFormulas.first); + auto tasks = this->getTasks(modelFormulas.second); + EXPECT_EQ(169ul, model->getNumberOfStates()); + EXPECT_EQ(436ul, model->getNumberOfTransitions()); + ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); + auto mdp = model->template as>(); + storm::modelchecker::SparseMdpPrctlModelChecker> checker(*mdp); + + auto result = checker.check(this->env(), tasks[0])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[1])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[2])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[3])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[4])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("0"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[5])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("0"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[6])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("1"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[7])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("1"), result[*mdp->getInitialStates().begin()], this->precision()); +} + +TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, consensus) { + typedef typename TestFixture::ValueType ValueType; + + std::string const formulasString = + "Pmax=? [F \"all_coins_equal_0\" & \"finished\" || F \"agree\" & \"finished\"];" + "Pmin=? [F \"all_coins_equal_0\" & \"finished\" || F \"agree\" & \"finished\"];" + "Pmax=? [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];" + "Pmin=? [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];"; + + auto program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm"); + auto modelFormulas = this->buildModelFormulas(program, formulasString); + auto model = std::move(modelFormulas.first); + auto tasks = this->getTasks(modelFormulas.second); + EXPECT_EQ(272ul, model->getNumberOfStates()); + EXPECT_EQ(492ul, model->getNumberOfTransitions()); + ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); + auto mdp = model->template as>(); + storm::modelchecker::SparseMdpPrctlModelChecker> checker(*mdp); + + auto result = checker.check(this->env(), tasks[0])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("561/953"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[1])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("392/953"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[2])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("561/953"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[3])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("392/953"), result[*mdp->getInitialStates().begin()], this->precision()); +} + +TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, simple) { + typedef typename TestFixture::ValueType ValueType; + + std::string const programAsString = R"(mdp +module main + x : [0..2]; + [] x=0 -> 0.7 : (x'=1) + 0.3 : (x'=2); + [] x=1 -> 1 : (x'=1); + [] x=2 -> 1 : (x'=1); +endmodule +)"; + + std::string const formulasString = + "Pmin=? [F x=2 || F x=1];" + "Pmax=? [F x=2 || F x=1];"; + + auto program = storm::parser::PrismParser::parseFromString(programAsString, ""); + auto modelFormulas = this->buildModelFormulas(program, formulasString); + auto model = std::move(modelFormulas.first); + auto tasks = this->getTasks(modelFormulas.second); + EXPECT_EQ(3ul, model->getNumberOfStates()); + EXPECT_EQ(4ul, model->getNumberOfTransitions()); + ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); + auto mdp = model->template as>(); + storm::modelchecker::SparseMdpPrctlModelChecker> checker(*mdp); + + auto result = checker.check(this->env(), tasks[0])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("3/10"), result[*mdp->getInitialStates().begin()], this->precision()); + result = checker.check(this->env(), tasks[1])->template asExplicitQuantitativeCheckResult(); + EXPECT_NEAR(this->parseNumber("3/10"), result[*mdp->getInitialStates().begin()], this->precision()); +} + +} // namespace From fd2af7ca7d43e9cac52ad0698d824b6f2155b104 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sat, 5 Jul 2025 09:44:32 +0200 Subject: [PATCH 031/102] fix formatting --- src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h index 30bde72e64..105c152605 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h @@ -91,7 +91,7 @@ class SparseMdpPrctlHelper { storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative); - + private: static MDPSparseModelCheckingHelperReturnType computeReachabilityRewardsHelper( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, From 0b1bce3fd01d6d528e7cc735424163bb02734074 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sun, 6 Jul 2025 07:33:06 +0200 Subject: [PATCH 032/102] Fix issue in restart method --- src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index f70a4dc843..8bd104cacd 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -289,7 +289,7 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init // Eliminate end components in two phases // First, we catch all end components that do not contain the initial state. It is possible to stay in those ECs forever // without reaching the condition. This is reflected by a backloop to the initial state. - storm::storage::BitVector selectedStatesInMatrix(numMaybeChoices, true); + storm::storage::BitVector selectedStatesInMatrix(numMaybeStates, true); selectedStatesInMatrix.set(initStateInMatrix, false); eliminateEndComponents(selectedStatesInMatrix, true, initStateInMatrix, matrix, initStateInMatrix, rowsWithSum1, rowValues); // Second, eliminate the remaining ECs. These must involve the initial state and might have been introduced in the previous step. From e2427abbab3ce0b0c402e183460ed4cb1e502acf Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Tue, 8 Jul 2025 23:35:51 +0200 Subject: [PATCH 033/102] Implemented suggestion by sjunges - remove unnecessary include - rename ConditionalAlgorithm to ConditionalAlgorithmSetting - rename targetValue to getTargetValue - reordered some assignments when computing normal form. - elaborate on normal form precision factor --- .../modelchecker/ModelCheckerEnvironment.cpp | 10 +++--- .../modelchecker/ModelCheckerEnvironment.h | 8 ++--- .../helper/conditional/ConditionalAlgorithm.h | 13 ------- ...hm.cpp => ConditionalAlgorithmSetting.cpp} | 26 +++++++------- .../conditional/ConditionalAlgorithmSetting.h | 13 +++++++ .../helper/conditional/ConditionalHelper.cpp | 36 ++++++++++--------- .../settings/modules/ModelCheckerSettings.cpp | 8 ++--- .../settings/modules/ModelCheckerSettings.h | 4 +-- .../ConditionalMdpPrctlModelCheckerTest.cpp | 16 ++++----- 9 files changed, 66 insertions(+), 68 deletions(-) delete mode 100644 src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h rename src/storm/modelchecker/helper/conditional/{ConditionalAlgorithm.cpp => ConditionalAlgorithmSetting.cpp} (52%) create mode 100644 src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp index f88e3849c1..5ff79fd9a3 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp @@ -20,7 +20,7 @@ ModelCheckerEnvironment::ModelCheckerEnvironment() { auto const& ioSettings = storm::settings::getModule(); steadyStateDistributionAlgorithm = ioSettings.getSteadyStateDistributionAlgorithm(); - conditionalAlgorithm = mcSettings.getConditionalAlgorithm(); + conditionalAlgorithmSetting = mcSettings.getConditionalAlgorithmSetting(); } ModelCheckerEnvironment::~ModelCheckerEnvironment() { @@ -35,12 +35,12 @@ void ModelCheckerEnvironment::setSteadyStateDistributionAlgorithm(SteadyStateDis steadyStateDistributionAlgorithm = value; } -ConditionalAlgorithm ModelCheckerEnvironment::getConditionalAlgorithm() const { - return conditionalAlgorithm; +ConditionalAlgorithmSetting ModelCheckerEnvironment::getConditionalAlgorithmSetting() const { + return conditionalAlgorithmSetting; } -void ModelCheckerEnvironment::setConditionalAlgorithm(ConditionalAlgorithm value) { - conditionalAlgorithm = value; +void ModelCheckerEnvironment::setConditionalAlgorithmSetting(ConditionalAlgorithmSetting value) { + conditionalAlgorithmSetting = value; } MultiObjectiveModelCheckerEnvironment& ModelCheckerEnvironment::multi() { diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h index 162add631f..fce3e9e337 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h @@ -6,7 +6,7 @@ #include "storm/environment/Environment.h" #include "storm/environment/SubEnvironment.h" -#include "storm/modelchecker/helper/conditional/ConditionalAlgorithm.h" +#include "storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h" #include "storm/modelchecker/helper/infinitehorizon/SteadyStateDistributionAlgorithm.h" namespace storm { @@ -25,8 +25,8 @@ class ModelCheckerEnvironment { SteadyStateDistributionAlgorithm getSteadyStateDistributionAlgorithm() const; void setSteadyStateDistributionAlgorithm(SteadyStateDistributionAlgorithm value); - ConditionalAlgorithm getConditionalAlgorithm() const; - void setConditionalAlgorithm(ConditionalAlgorithm value); + ConditionalAlgorithmSetting getConditionalAlgorithmSetting() const; + void setConditionalAlgorithmSetting(ConditionalAlgorithmSetting value); bool isLtl2daToolSet() const; std::string const& getLtl2daTool() const; @@ -37,6 +37,6 @@ class ModelCheckerEnvironment { SubEnvironment multiObjectiveModelCheckerEnvironment; boost::optional ltl2daTool; SteadyStateDistributionAlgorithm steadyStateDistributionAlgorithm; - ConditionalAlgorithm conditionalAlgorithm; + ConditionalAlgorithmSetting conditionalAlgorithmSetting; }; } // namespace storm diff --git a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h deleted file mode 100644 index d24b8bbdb8..0000000000 --- a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include - -#include "storm/exceptions/UnexpectedException.h" -#include "storm/utility/macros.h" - -namespace storm { -enum class ConditionalAlgorithm { Default, Restart, Bisection, BisectionAdvanced, PolicyIteration }; - -std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithm const& algorithm); -ConditionalAlgorithm conditionalAlgorithmFromString(std::string const& algorithm); - -} // namespace storm \ No newline at end of file diff --git a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.cpp b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.cpp similarity index 52% rename from src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.cpp rename to src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.cpp index ba494fb4e9..e909df6278 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithm.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.cpp @@ -1,34 +1,34 @@ -#include "ConditionalAlgorithm.h" +#include "ConditionalAlgorithmSetting.h" namespace storm { -std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithm const& algorithm) { +std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithmSetting const& algorithm) { switch (algorithm) { - case ConditionalAlgorithm::Default: + case ConditionalAlgorithmSetting::Default: return stream << "default"; - case ConditionalAlgorithm::Restart: + case ConditionalAlgorithmSetting::Restart: return stream << "restart"; - case ConditionalAlgorithm::Bisection: + case ConditionalAlgorithmSetting::Bisection: return stream << "bisection"; - case ConditionalAlgorithm::BisectionAdvanced: + case ConditionalAlgorithmSetting::BisectionAdvanced: return stream << "bisection-advanced"; - case ConditionalAlgorithm::PolicyIteration: + case ConditionalAlgorithmSetting::PolicyIteration: return stream << "pi"; } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unknown conditional algorithm"); return stream; } -ConditionalAlgorithm conditionalAlgorithmFromString(std::string const& algorithm) { +ConditionalAlgorithmSetting conditionalAlgorithmSettingFromString(std::string const& algorithm) { if (algorithm == "default") { - return ConditionalAlgorithm::Default; + return ConditionalAlgorithmSetting::Default; } else if (algorithm == "restart") { - return ConditionalAlgorithm::Restart; + return ConditionalAlgorithmSetting::Restart; } else if (algorithm == "bisection") { - return ConditionalAlgorithm::Bisection; + return ConditionalAlgorithmSetting::Bisection; } else if (algorithm == "bisection-advanced") { - return ConditionalAlgorithm::BisectionAdvanced; + return ConditionalAlgorithmSetting::BisectionAdvanced; } else if (algorithm == "pi") { - return ConditionalAlgorithm::PolicyIteration; + return ConditionalAlgorithmSetting::PolicyIteration; } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unknown conditional algorithm: " << algorithm); } diff --git a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h new file mode 100644 index 0000000000..4a9440abb4 --- /dev/null +++ b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h @@ -0,0 +1,13 @@ +#pragma once +#include + +#include "storm/exceptions/UnexpectedException.h" +#include "storm/utility/macros.h" + +namespace storm { +enum class ConditionalAlgorithmSetting { Default, Restart, Bisection, BisectionAdvanced, PolicyIteration }; + +std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithmSetting const& algorithm); +ConditionalAlgorithmSetting conditionalAlgorithmSettingFromString(std::string const& algorithm); + +} // namespace storm \ No newline at end of file diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 8bd104cacd..866c158a42 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -154,7 +154,7 @@ struct NormalFormData { // TerminalStates is a superset of conditionStates and dom(nonZeroTargetStateValues). // For a terminalState that is not a conditionState, it is impossible to (reach the condition and not reach the target). - ValueType targetValue(uint64_t state) const { + ValueType getTargetValue(uint64_t state) const { STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get target value for non-terminal state"); auto const it = nonZeroTargetStateValues.find(state); return it == nonZeroTargetStateValues.end() ? storm::utility::zero() : it->second; @@ -164,7 +164,7 @@ struct NormalFormData { STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get fail probability for non-terminal state"); STORM_LOG_ASSERT(!conditionStates.get(state), "Tried to get fail probability for a condition state"); // condition states have fail probability zero - return storm::utility::one() - targetValue(state); + return storm::utility::one() - getTargetValue(state); } }; @@ -184,8 +184,6 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates); computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); - auto terminalStates = extendedConditionStates | extendedTargetStates | universalObservationFailureStates; - // get states where the optimal policy reaches the condition with positive probability auto terminalStatesThatReachCondition = extendedConditionStates; for (auto state : targetAndNotCondFailStates) { @@ -194,6 +192,8 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver } } + // get the terminal states following the three cases described above + auto terminalStates = extendedConditionStates | extendedTargetStates | universalObservationFailureStates; if (storm::solver::minimize(dir)) { // There can be target states from which (only) the *minimal* probability to reach a condition is zero. // For those states, the optimal policy is to enforce observation failure. @@ -247,7 +247,7 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init bool rowSumIsLess1 = false; for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { if (normalForm.terminalStates.get(entry.getColumn())) { - ValueType const targetValue = normalForm.targetValue(entry.getColumn()); + ValueType const targetValue = normalForm.getTargetValue(entry.getColumn()); targetProbability += targetValue * entry.getValue(); if (normalForm.conditionStates.get(entry.getColumn())) { rowSumIsLess1 = true; @@ -379,7 +379,7 @@ class WeightedReachabilityHelper { if (normalForm.terminalStates.get(entry.getColumn())) { STORM_LOG_ASSERT(!storm::utility::isZero(entry.getValue()), "Transition probability must be non-zero"); rowSumIsLess1 = true; - ValueType const scaledTargetValue = normalForm.targetValue(entry.getColumn()) * entry.getValue(); + ValueType const scaledTargetValue = normalForm.getTargetValue(entry.getColumn()) * entry.getValue(); targetProbability += scaledTargetValue; if (normalForm.conditionStates.get(entry.getColumn())) { conditionProbability += entry.getValue(); // conditionValue of successor is 1 @@ -671,7 +671,7 @@ std::optional handleTrivialCases(uint64_t const initialState, Norm if (normalForm.terminalStates.get(initialState)) { STORM_LOG_DEBUG("Initial state is terminal."); if (normalForm.conditionStates.get(initialState)) { - return normalForm.targetValue(initialState); // The value is already known, nothing to do. + return normalForm.getTargetValue(initialState); // The value is already known, nothing to do. } else { STORM_LOG_THROW(!normalForm.universalObservationFailureStates.get(initialState), storm::exceptions::NotSupportedException, "Trying to compute undefined conditional probability: the condition has probability 0 under all policies."); @@ -699,10 +699,12 @@ std::unique_ptr computeConditionalProbabilities(Environment const& auto normalFormConstructionEnv = env; auto analysisEnv = env; if (env.solver().isForceSoundness()) { - normalFormConstructionEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * - storm::utility::convertNumber("1/10")); + // We intuitively have to divide the precision into two parts, one for computations when constructing the normal form and one for the actual analysis. + // As the former is usually less numerically challenging, we use a factor of 1/10 for the normal form construction and 9/10 for the analysis. + auto const normalFormPrecisionFactor = storm::utility::convertNumber("1/10"); + normalFormConstructionEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * normalFormPrecisionFactor); analysisEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * - storm::utility::convertNumber("9/10")); + (storm::utility::one() - normalFormPrecisionFactor)); } // We first translate the problem into a normal form. @@ -727,25 +729,25 @@ std::unique_ptr computeConditionalProbabilities(Environment const& STORM_LOG_DEBUG("Initial state has trivial value " << initialStateValue); } else { STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState), "Initial state must be a maybe state if it is not a terminal state"); - auto alg = analysisEnv.modelchecker().getConditionalAlgorithm(); - if (alg == ConditionalAlgorithm::Default) { - alg = ConditionalAlgorithm::Restart; + auto alg = analysisEnv.modelchecker().getConditionalAlgorithmSetting(); + if (alg == ConditionalAlgorithmSetting::Default) { + alg = ConditionalAlgorithmSetting::Restart; } STORM_LOG_INFO("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg << "."); // sw.restart(); switch (alg) { - case ConditionalAlgorithm::Restart: + case ConditionalAlgorithmSetting::Restart: initialStateValue = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); break; - case ConditionalAlgorithm::Bisection: + case ConditionalAlgorithmSetting::Bisection: initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal.direction(), transitionMatrix, normalFormData); break; - case ConditionalAlgorithm::BisectionAdvanced: + case ConditionalAlgorithmSetting::BisectionAdvanced: initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal.direction(), transitionMatrix, normalFormData); break; - case ConditionalAlgorithm::PolicyIteration: + case ConditionalAlgorithmSetting::PolicyIteration: initialStateValue = internal::computeViaPolicyIteration(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); break; default: diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index 0c0e123e93..7806c9abc7 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -4,12 +4,8 @@ #include "storm/settings/ArgumentBuilder.h" #include "storm/settings/Option.h" #include "storm/settings/OptionBuilder.h" -#include "storm/settings/SettingMemento.h" #include "storm/settings/SettingsManager.h" -#include "storm/exceptions/NotImplementedException.h" -#include "storm/utility/macros.h" - namespace storm::settings::modules { const std::string ModelCheckerSettings::moduleName = "modelchecker"; @@ -56,8 +52,8 @@ bool ModelCheckerSettings::isConditionalAlgorithmSet() const { return this->getOption(conditionalAlgorithmOptionName).getHasOptionBeenSet(); } -ConditionalAlgorithm ModelCheckerSettings::getConditionalAlgorithm() const { - return conditionalAlgorithmFromString(this->getOption(conditionalAlgorithmOptionName).getArgumentByName("name").getValueAsString()); +ConditionalAlgorithmSetting ModelCheckerSettings::getConditionalAlgorithmSetting() const { + return conditionalAlgorithmSettingFromString(this->getOption(conditionalAlgorithmOptionName).getArgumentByName("name").getValueAsString()); } } // namespace storm::settings::modules diff --git a/src/storm/settings/modules/ModelCheckerSettings.h b/src/storm/settings/modules/ModelCheckerSettings.h index 6643236b64..ce7e5bd234 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.h +++ b/src/storm/settings/modules/ModelCheckerSettings.h @@ -1,7 +1,7 @@ #pragma once #include "storm-config.h" -#include "storm/modelchecker/helper/conditional/ConditionalAlgorithm.h" +#include "storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h" #include "storm/settings/modules/ModuleSettings.h" namespace storm { @@ -42,7 +42,7 @@ class ModelCheckerSettings : public ModuleSettings { /*! * Retrieves the specified algorithm for conditional probabilities. */ - ConditionalAlgorithm getConditionalAlgorithm() const; + ConditionalAlgorithmSetting getConditionalAlgorithmSetting() const; // The name of the module. static const std::string moduleName; diff --git a/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp index 90aac45102..f362b0fbe4 100644 --- a/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp @@ -22,7 +22,7 @@ class SparseDoubleRestartEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Restart); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::Restart); env.solver().minMax().setPrecision(storm::utility::convertNumber(1e-10)); // restart algorithm requires a higher precision return env; } @@ -35,7 +35,7 @@ class SparseDoubleBisectionEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Bisection); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::Bisection); return env; } }; @@ -47,7 +47,7 @@ class SparseDoubleBisectionAdvancedEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::BisectionAdvanced); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionAdvanced); return env; } }; @@ -59,7 +59,7 @@ class SparseDoublePiEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::PolicyIteration); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::PolicyIteration); return env; } }; @@ -71,7 +71,7 @@ class SparseRationalNumberRestartEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Restart); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::Restart); env.solver().minMax().setPrecision(storm::utility::convertNumber(1e-10)); // restart algorithm requires a higher precision return env; } @@ -84,7 +84,7 @@ class SparseRationalNumberBisectionEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::Bisection); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::Bisection); return env; } }; @@ -96,7 +96,7 @@ class SparseRationalNumberBisectionAdvancedEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::BisectionAdvanced); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionAdvanced); return env; } }; @@ -108,7 +108,7 @@ class SparseRationalNumberPiEnvironment { typedef storm::models::sparse::Mdp ModelType; static storm::Environment createEnvironment() { storm::Environment env; - env.modelchecker().setConditionalAlgorithm(storm::ConditionalAlgorithm::PolicyIteration); + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::PolicyIteration); return env; } }; From da862da7ce37862429bc782a64ffb662426db3ca Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 9 Jul 2025 00:30:39 +0200 Subject: [PATCH 034/102] added `bool BitVector::hasUniqueSetBit() const` --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 3 +-- src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp | 2 +- src/storm/storage/BitVector.cpp | 4 ++++ src/storm/storage/BitVector.h | 5 +++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 866c158a42..1d36640485 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -711,7 +711,7 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // @see doi.org/10.1007/978-3-642-54862-8_43 STORM_LOG_THROW(goal.hasRelevantValues(), storm::exceptions::NotSupportedException, "No initial state given. Conditional probabilities can only be computed for models with a single initial state."); - STORM_LOG_THROW(goal.relevantValues().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, + STORM_LOG_THROW(goal.relevantValues().hasUniqueSetBit(), storm::exceptions::NotSupportedException, "Only one initial state is supported for conditional probabilities"); STORM_LOG_TRACE("Computing conditional probabilities for a model with " << transitionMatrix.getRowGroupCount() << " states and " << transitionMatrix.getEntryCount() << " transitions."); @@ -721,7 +721,6 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // sw.stop(); // STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); // Then, we solve the induced problem using the selected algorithm - STORM_LOG_ASSERT(goal.relevantValues().getNumberOfSetBits() == 1, "Only one initial state is supported for conditional probabilities"); auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); if (auto trivialValue = internal::handleTrivialCases(initialState, normalFormData); trivialValue.has_value()) { diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index dd9c352850..b71f2ca7e2 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -263,7 +263,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::logic::ConditionalFormula const& conditionalFormula = checkTask.getFormula(); STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); - STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::InvalidPropertyException, + STORM_LOG_THROW(this->getModel().getInitialStates().hasUniqueSetBit(), storm::exceptions::InvalidPropertyException, "Cannot compute conditional probabilities on MDPs with more than one initial state."); STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidPropertyException, "Conditional probabilities can only be computed for the initial states of the model."); diff --git a/src/storm/storage/BitVector.cpp b/src/storm/storage/BitVector.cpp index 5b390dde58..626e48f14e 100644 --- a/src/storm/storage/BitVector.cpp +++ b/src/storm/storage/BitVector.cpp @@ -771,6 +771,10 @@ std::vector BitVector::getNumberOfSetBitsBeforeIndices() const { return bitsSetBeforeIndices; } +bool BitVector::hasUniqueSetBit() const { + return getNumberOfSetBits() == 1; +} + size_t BitVector::size() const { return static_cast(bitCount); } diff --git a/src/storm/storage/BitVector.h b/src/storm/storage/BitVector.h index 49332d1b78..afc808acff 100644 --- a/src/storm/storage/BitVector.h +++ b/src/storm/storage/BitVector.h @@ -593,6 +593,11 @@ class BitVector { */ std::vector getNumberOfSetBitsBeforeIndices() const; + /* + * @return True, if the number of set bits is 1, false otherwise. + */ + bool hasUniqueSetBit() const; + /*! * Retrieves the number of bits this bit vector can store. * From c3fd4050977c6f3aa510152d36b2a598699093b8 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 9 Jul 2025 14:10:55 +0200 Subject: [PATCH 035/102] wip interval multiplier --- .../SparseNondeterministicStepBoundedHorizonHelper.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp index 02cb13fbca..35c061e870 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp @@ -1,4 +1,5 @@ #include "storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/modelchecker/hints/ExplicitModelCheckerHint.h" #include "storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.h" @@ -84,6 +85,8 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper template class SparseNondeterministicStepBoundedHorizonHelper; template class SparseNondeterministicStepBoundedHorizonHelper; +template class SparseNondeterministicStepBoundedHorizonHelper; +template class SparseNondeterministicStepBoundedHorizonHelper; } // namespace helper } // namespace modelchecker } // namespace storm \ No newline at end of file From 6ef845bbfbfda1382199ec1fd1a1e3df0c3ac0c8 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 9 Jul 2025 17:31:42 +0200 Subject: [PATCH 036/102] added bounded until model checking for iMDPs --- ...ndeterministicStepBoundedHorizonHelper.cpp | 31 +++--- ...NondeterministicStepBoundedHorizonHelper.h | 12 +- .../prctl/SparseMdpPrctlModelChecker.cpp | 50 +++++---- .../prctl/helper/SparseMdpPrctlHelper.cpp | 105 ++++++++++-------- .../solver/helper/ValueIterationOperator.h | 13 ++- src/storm/solver/multiplier/Multiplier.cpp | 69 +++++++----- src/storm/solver/multiplier/Multiplier.h | 29 ++--- .../multiplier/ViOperatorMultiplier.cpp | 90 ++++++++------- .../solver/multiplier/ViOperatorMultiplier.h | 17 +-- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 2 +- 10 files changed, 233 insertions(+), 185 deletions(-) diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp index 35c061e870..d262dd609a 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp @@ -1,4 +1,5 @@ #include "storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h" +#include "storm/adapters/RationalNumberAdapter.h" #include "storm/adapters/RationalNumberForward.h" #include "storm/modelchecker/hints/ExplicitModelCheckerHint.h" #include "storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.h" @@ -18,22 +19,20 @@ namespace storm { namespace modelchecker { namespace helper { -template -SparseNondeterministicStepBoundedHorizonHelper::SparseNondeterministicStepBoundedHorizonHelper( +template +SparseNondeterministicStepBoundedHorizonHelper::SparseNondeterministicStepBoundedHorizonHelper( /*storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions*/) // transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions) { // Intentionally left empty. } -template -std::vector SparseNondeterministicStepBoundedHorizonHelper::compute(Environment const& env, storm::solver::SolveGoal&& goal, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, - storm::storage::BitVector const& phiStates, - storm::storage::BitVector const& psiStates, uint64_t lowerBound, - uint64_t upperBound, ModelCheckerHint const& hint) { - std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); +template +std::vector SparseNondeterministicStepBoundedHorizonHelper::compute( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + uint64_t lowerBound, uint64_t upperBound, ModelCheckerHint const& hint) { + std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); storm::storage::BitVector makeZeroColumns; // Determine the states that have 0 probability of reaching the target states. @@ -62,15 +61,15 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper std::vector b = transitionMatrix.getConstrainedRowGroupSumVector(maybeStates, psiStates); // Create the vector with which to multiply. - std::vector subresult(maybeStates.getNumberOfSetBits()); + std::vector subresult(maybeStates.getNumberOfSetBits()); - auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); + auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); if (lowerBound == 0) { multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound); } else { multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound - lowerBound + 1); storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); - auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); + auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); b = std::vector(b.size(), storm::utility::zero()); multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, lowerBound - 1); } @@ -78,15 +77,15 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper storm::utility::vector::setVectorValues(result, maybeStates, subresult); } if (lowerBound == 0) { - storm::utility::vector::setVectorValues(result, psiStates, storm::utility::one()); + storm::utility::vector::setVectorValues(result, psiStates, storm::utility::one()); } return result; } template class SparseNondeterministicStepBoundedHorizonHelper; template class SparseNondeterministicStepBoundedHorizonHelper; -template class SparseNondeterministicStepBoundedHorizonHelper; -template class SparseNondeterministicStepBoundedHorizonHelper; +template class SparseNondeterministicStepBoundedHorizonHelper; +template class SparseNondeterministicStepBoundedHorizonHelper; } // namespace helper } // namespace modelchecker } // namespace storm \ No newline at end of file diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h index fae2a12eae..304cee3ed9 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h @@ -10,15 +10,15 @@ namespace storm { namespace modelchecker { namespace helper { -template +template class SparseNondeterministicStepBoundedHorizonHelper { public: SparseNondeterministicStepBoundedHorizonHelper(); - std::vector compute(Environment const& env, storm::solver::SolveGoal&& goal, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, - storm::storage::BitVector const& psiStates, uint64_t lowerBound, uint64_t upperBound, - ModelCheckerHint const& hint = ModelCheckerHint()); + std::vector compute(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates, uint64_t lowerBound, uint64_t upperBound, + ModelCheckerHint const& hint = ModelCheckerHint()); private: }; diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index f56e352183..35ad78c556 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -2,6 +2,7 @@ #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/InvalidStateException.h" +#include "storm/logic/BoundedUntilFormula.h" #include "storm/logic/FragmentSpecification.h" #include "storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h" #include "storm/modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h" @@ -43,6 +44,9 @@ bool SparseMdpPrctlModelChecker::canHandleStatic(CheckTask::canHandle(CheckTask std::unique_ptr SparseMdpPrctlModelChecker::computeBoundedUntilProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented bounded until with intervals"); - return nullptr; - } else { - storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); - STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, - "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); - if (pathFormula.isMultiDimensional() || pathFormula.getTimeBoundReference().isRewardBound()) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, + "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + if (pathFormula.isMultiDimensional() || pathFormula.getTimeBoundReference().isRewardBound()) { + if constexpr (std::is_same_v || std::is_same_v) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented multi dimensional bounded until with intervals"); + return nullptr; + } else { STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, "Checking non-trivial bounded until probabilities can only be computed for the initial states of the model."); STORM_LOG_WARN_COND(!checkTask.isQualitativeSet(), "Checking non-trivial bounded until formulas is not optimized w.r.t. qualitative queries"); @@ -128,23 +132,21 @@ std::unique_ptr SparseMdpPrctlModelChecker::com auto numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeRewardBoundedValues( env, checkTask.getOptimizationDirection(), rewardUnfolding, this->getModel().getInitialStates()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); - } else { - STORM_LOG_THROW(pathFormula.hasUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have (a single) upper step bound."); - STORM_LOG_THROW(pathFormula.hasIntegerLowerBound(), storm::exceptions::InvalidPropertyException, - "Formula lower step bound must be discrete/integral."); - STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, - "Formula needs to have discrete upper time bound."); - std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); - std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; - std::vector numericResult = - helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), - this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), - pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound(), checkTask.getHint()); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } + } else { + STORM_LOG_THROW(pathFormula.hasUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have (a single) upper step bound."); + STORM_LOG_THROW(pathFormula.hasIntegerLowerBound(), storm::exceptions::InvalidPropertyException, "Formula lower step bound must be discrete/integral."); + STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper time bound."); + std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); + std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; + std::vector numericResult = + helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), + this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), + pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound(), checkTask.getHint()); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } } diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 19c14dda63..40ba777ac0 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -149,7 +149,7 @@ std::vector SparseMdpPrctlHelper::compute Environment const& env, OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates) { if constexpr (std::is_same_v || std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with reward models."); + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with interval models."); } else { // Create the vector with which to multiply and initialize it correctly. std::vector result(transitionMatrix.getRowGroupCount()); @@ -1022,37 +1022,38 @@ std::vector SparseMdpPrctlHelper::compute // Only compute the result if the reward model is not empty. STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support rational interval rewards with double interval models."); - } else { - return computeReachabilityRewardsHelper( - env, std::move(goal), transitionMatrix, backwardTransitions, - [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { - std::vector result; - result.reserve(rowCount); - std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); - for (auto const& interval : subIntervalVector) { - result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); - } - return result; - }, - targetStates, qualitative, false, - [&]() { - return intervalRewardModel.getStatesWithFilter( - transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); - }, - [&]() { - return intervalRewardModel.getChoicesWithFilter( - transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); - }) - .values; - } + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support rational interval rewards with double interval models."); + } else { + return computeReachabilityRewardsHelper( + env, std::move(goal), transitionMatrix, backwardTransitions, + [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + std::vector result; + result.reserve(rowCount); + std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); + for (auto const& interval : subIntervalVector) { + result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); + } + return result; + }, + targetStates, qualitative, false, + [&]() { + return intervalRewardModel.getStatesWithFilter( + transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }, + [&]() { + return intervalRewardModel.getChoicesWithFilter( + transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }) + .values; + } } template std::vector SparseMdpPrctlHelper::computeReachabilityRewards( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, - bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative) { + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, + storm::storage::BitVector const& targetStates, bool qualitative) { // Only compute the result if the reward model is not empty. STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); if constexpr (std::is_same_v) { @@ -1063,7 +1064,8 @@ std::vector SparseMdpPrctlHelper::compute [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { std::vector result; result.reserve(rowCount); - std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); + std::vector subIntervalVector = + intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); for (auto const& interval : subIntervalVector) { result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); } @@ -1071,12 +1073,14 @@ std::vector SparseMdpPrctlHelper::compute }, targetStates, qualitative, false, [&]() { - return intervalRewardModel.getStatesWithFilter( - transitionMatrix, [&](storm::RationalInterval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + return intervalRewardModel.getStatesWithFilter(transitionMatrix, [&](storm::RationalInterval const& i) { + return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); + }); }, [&]() { - return intervalRewardModel.getChoicesWithFilter( - transitionMatrix, [&](storm::RationalInterval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + return intervalRewardModel.getChoicesWithFilter(transitionMatrix, [&](storm::RationalInterval const& i) { + return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); + }); }) .values; } @@ -1091,10 +1095,11 @@ std::vector SparseMdpPrctlHelper:: } template<> -std::vector SparseMdpPrctlHelper::computeReachabilityRewards( - Environment const& env, storm::solver::SolveGoal&&, storm::storage::SparseMatrix const&, - storm::storage::SparseMatrix const&, storm::models::sparse::StandardRewardModel const&, bool, - storm::storage::BitVector const&, bool) { +std::vector SparseMdpPrctlHelper::computeReachabilityRewards(Environment const& env, storm::solver::SolveGoal&&, + storm::storage::SparseMatrix const&, + storm::storage::SparseMatrix const&, + storm::models::sparse::StandardRewardModel const&, bool, + storm::storage::BitVector const&, bool) { STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type."); } #endif @@ -1715,19 +1720,27 @@ template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper; template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards( - Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepCount); template std::vector SparseMdpPrctlHelper::computeCumulativeRewards( - Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepBound); -template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards( - Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, - storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint); -template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeTotalRewards( - Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, - bool qualitative, bool produceScheduler, ModelCheckerHint const& hint); +template MDPSparseModelCheckingHelperReturnType +SparseMdpPrctlHelper::computeReachabilityRewards( + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, + bool produceScheduler, ModelCheckerHint const& hint); +template MDPSparseModelCheckingHelperReturnType +SparseMdpPrctlHelper::computeTotalRewards( + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& rewardModel, bool qualitative, bool produceScheduler, + ModelCheckerHint const& hint); } // namespace helper } // namespace modelchecker diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index fa286026ee..43803abb2f 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -240,6 +240,15 @@ class ValueIterationOperator { return {(*offsets.first)[offsetIndex], offsets.second}; } + template + OpT robustInitializeRowRes(std::vector const&, OffT const& offsets, uint64_t offsetIndex) const { + if constexpr (RobustDirection == OptimizationDirection::Maximize) { + return offsets.upper(); + } else { + return offsets.lower(); + } + } + template OpT robustInitializeRowRes(std::vector const&, std::vector const& offsets, uint64_t offsetIndex) const { if constexpr (RobustDirection == OptimizationDirection::Maximize) { @@ -339,7 +348,7 @@ class ValueIterationOperator { result += operand[*matrixColumnIt] * lower; } remainingValue -= lower; - SolutionType const diameter = static_cast(- lower + matrixValueIt->upper()); + SolutionType const diameter = static_cast(-lower + matrixValueIt->upper()); if (!storm::utility::isZero(diameter)) { applyCache.robustOrder.emplace_back(operand[*matrixColumnIt], std::make_pair(diameter, orderCounter)); } @@ -468,7 +477,7 @@ class ValueIterationOperator { }; /*! - * Cache for robust value iteration, empty struct for other ValueTypes than storm::Interval. + * Cache for robust value iteration, empty struct for other ValueTypes than storm::Interval and storm::RationalInterval. */ ApplyCache applyCache; diff --git a/src/storm/solver/multiplier/Multiplier.cpp b/src/storm/solver/multiplier/Multiplier.cpp index c0c2199115..a33137a806 100644 --- a/src/storm/solver/multiplier/Multiplier.cpp +++ b/src/storm/solver/multiplier/Multiplier.cpp @@ -1,7 +1,9 @@ #include "storm/solver/multiplier/Multiplier.h" +#include #include "storm-config.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/storage/SparseMatrix.h" #include "storm/adapters/RationalFunctionAdapter.h" @@ -22,30 +24,33 @@ namespace storm { namespace solver { -template -Multiplier::Multiplier(storm::storage::SparseMatrix const& matrix) : matrix(matrix) { +template +Multiplier::Multiplier(storm::storage::SparseMatrix const& matrix) : matrix(matrix) { // Intentionally left empty. } -template -void Multiplier::clearCache() const { +template +void Multiplier::clearCache() const { cachedVector.reset(); } -template -void Multiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, - std::vector const* b, std::vector& result, std::vector* choices) const { +template +void Multiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, + std::vector const* b, std::vector& result, + std::vector* choices) const { multiplyAndReduce(env, dir, this->matrix.getRowGroupIndices(), x, b, result, choices); } -template -void Multiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, std::vector* choices, bool backwards) const { +template +void Multiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, + std::vector const* b, std::vector* choices, + bool backwards) const { multiplyAndReduceGaussSeidel(env, dir, this->matrix.getRowGroupIndices(), x, b, choices, backwards); } -template -void Multiplier::repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, uint64_t n) const { +template +void Multiplier::repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, + uint64_t n) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); @@ -59,9 +64,9 @@ void Multiplier::repeatedMultiply(Environment const& env, std::vector } } -template -void Multiplier::repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, uint64_t n) const { +template +void Multiplier::repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, + std::vector const* b, uint64_t n) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); @@ -74,39 +79,47 @@ void Multiplier::repeatedMultiplyAndReduce(Environment const& env, Op } } -template - -std::vector& Multiplier::provideCachedVector(uint64_t size) const { +template +std::vector& Multiplier::provideCachedVector(uint64_t size) const { if (this->cachedVector) { this->cachedVector->resize(size); } else { - this->cachedVector = std::make_unique>(size); + this->cachedVector = std::make_unique>(size); } return *this->cachedVector; } -template -std::unique_ptr> MultiplierFactory::create(Environment const& env, storm::storage::SparseMatrix const& matrix) { +template +std::unique_ptr> MultiplierFactory::create(Environment const& env, + storm::storage::SparseMatrix const& matrix) { auto type = env.solver().multiplier().getType(); // Adjust the type if the ValueType is not supported - if (type == MultiplierType::ViOperator && (std::is_same_v || std::is_same_v)) { + if (type == MultiplierType::ViOperator && + (std::is_same_v || (std::is_same_v && std::is_same_v) || + (std::is_same_v && std::is_same_v))) { STORM_LOG_INFO("Switching multiplier type from 'vioperator' to 'native' because the given ValueType is not supported by the VI Operator multiplier."); type = MultiplierType::Native; } switch (type) { case MultiplierType::ViOperator: - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (std::is_same_v || + (std::is_same_v && std::is_same_v) || + (std::is_same_v && std::is_same_v)) { throw storm::exceptions::NotImplementedException() << "VI Operator multiplier not supported with given value type."; } if (matrix.hasTrivialRowGrouping()) { - return std::make_unique>(matrix); + return std::make_unique>(matrix); } else { - return std::make_unique>(matrix); + return std::make_unique>(matrix); } case MultiplierType::Native: - return std::make_unique>(matrix); + if constexpr (std::is_same_v) { + return std::make_unique>(matrix); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Native multiplier not implemented for unequal ValueType and SolutionType."); + } } STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "Unknown MultiplierType"); } @@ -119,6 +132,10 @@ template class Multiplier; template class MultiplierFactory; template class Multiplier; template class MultiplierFactory; +template class Multiplier; +template class MultiplierFactory; +template class Multiplier; +template class MultiplierFactory; } // namespace solver } // namespace storm diff --git a/src/storm/solver/multiplier/Multiplier.h b/src/storm/solver/multiplier/Multiplier.h index 0d44d1cb17..35eca3600f 100644 --- a/src/storm/solver/multiplier/Multiplier.h +++ b/src/storm/solver/multiplier/Multiplier.h @@ -17,7 +17,7 @@ class SparseMatrix; namespace solver { -template +template class Multiplier { public: Multiplier(storm::storage::SparseMatrix const& matrix); @@ -39,7 +39,8 @@ class Multiplier { * @param result The target vector into which to write the multiplication result. Its length must be equal * to the number of rows of A. Can be the same as the x vector. */ - virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, std::vector& result) const = 0; + virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, + std::vector& result) const = 0; /*! * Performs a matrix-vector multiplication in gauss-seidel style. @@ -50,7 +51,7 @@ class Multiplier { * to the number of rows of A. * @param backwards if true, the iterations will be performed beginning from the last row and ending at the first row. */ - virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const = 0; + virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const = 0; /*! * Performs a matrix-vector multiplication x' = A*x + b and then minimizes/maximizes over the row groups @@ -66,10 +67,10 @@ class Multiplier { * to the number of rows of A. Can be the same as the x vector. * @param choices If given, the choices made in the reduction process are written to this vector. */ - void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, std::vector const* b, - std::vector& result, std::vector* choices = nullptr) const; + void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, std::vector const* b, + std::vector& result, std::vector* choices = nullptr) const; virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector const& x, std::vector const* b, std::vector& result, + std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const = 0; /*! @@ -87,10 +88,10 @@ class Multiplier { * @param choices If given, the choices made in the reduction process are written to this vector. * @param backwards if true, the iterations will be performed beginning from the last rowgroup and ending at the first rowgroup. */ - void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, + void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, std::vector* choices = nullptr, bool backwards = true) const; virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector& x, std::vector const* b, std::vector* choices = nullptr, + std::vector& x, std::vector const* b, std::vector* choices = nullptr, bool backwards = true) const = 0; /*! @@ -104,7 +105,7 @@ class Multiplier { * to the number of rows of A. * @param n The number of times to perform the multiplication. */ - void repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, uint64_t n) const; + void repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, uint64_t n) const; /*! * Performs repeated matrix-vector multiplication x' = A*x + b and then minimizes/maximizes over the row groups @@ -119,23 +120,23 @@ class Multiplier { * to the number of rows of A. * @param n The number of times to perform the multiplication. */ - void repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, + void repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, uint64_t n) const; protected: - std::vector& provideCachedVector(uint64_t size) const; + std::vector& provideCachedVector(uint64_t size) const; - mutable std::unique_ptr> cachedVector; + mutable std::unique_ptr> cachedVector; storm::storage::SparseMatrix const& matrix; }; -template +template class MultiplierFactory { public: MultiplierFactory() = default; ~MultiplierFactory() = default; - std::unique_ptr> create(Environment const& env, storm::storage::SparseMatrix const& matrix); + std::unique_ptr> create(Environment const& env, storm::storage::SparseMatrix const& matrix); }; } // namespace solver diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp index 4296e5077e..e3011fb094 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp @@ -1,6 +1,7 @@ #include "ViOperatorMultiplier.h" #include "storm/adapters/RationalNumberAdapter.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/solver/helper/ValueIterationOperator.h" #include "storm/storage/SparseMatrix.h" @@ -22,12 +23,9 @@ enum class BackendOptimizationDirection { None, Minimize, Maximize }; template class MultiplierBackend { public: - MultiplierBackend() - requires(!TrackChoices) - : choiceTracking(std::nullopt) {}; + MultiplierBackend() requires(!TrackChoices) : choiceTracking(std::nullopt){}; - MultiplierBackend(std::vector& choices, std::vector const& rowGroupIndices) - requires TrackChoices + MultiplierBackend(std::vector& choices, std::vector const& rowGroupIndices) requires TrackChoices : choiceTracking({choices, rowGroupIndices}) { // intentionally left empty. } @@ -108,7 +106,7 @@ class MultiplierBackend { template class PlainMultiplicationBackend { public: - PlainMultiplicationBackend(std::vector& rowResults) : rowResults(rowResults) {}; + PlainMultiplicationBackend(std::vector& rowResults) : rowResults(rowResults){}; void startNewIteration() { // intentionally left empty. @@ -144,14 +142,15 @@ class PlainMultiplicationBackend { } // namespace detail -template -ViOperatorMultiplier::ViOperatorMultiplier(storm::storage::SparseMatrix const& matrix) - : Multiplier(matrix) { +template +ViOperatorMultiplier::ViOperatorMultiplier(storm::storage::SparseMatrix const& matrix) + : Multiplier(matrix) { // Intentionally left empty. } -template -typename ViOperatorMultiplier::ViOpT& ViOperatorMultiplier::initialize() const { +template +typename ViOperatorMultiplier::ViOpT& +ViOperatorMultiplier::initialize() const { if (!viOperatorFwd) { return initialize(false); // default to backward operator } else { @@ -159,8 +158,9 @@ typename ViOperatorMultiplier::ViOpT& ViOperatorM } } -template -typename ViOperatorMultiplier::ViOpT& ViOperatorMultiplier::initialize(bool backwards) const { +template +typename ViOperatorMultiplier::ViOpT& +ViOperatorMultiplier::initialize(bool backwards) const { auto& viOp = backwards ? viOperatorBwd : viOperatorFwd; if (!viOp) { viOp = std::make_unique(); @@ -173,9 +173,9 @@ typename ViOperatorMultiplier::ViOpT& ViOperatorM return *viOp; } -template -void ViOperatorMultiplier::multiply(Environment const& env, std::vector const& x, std::vector const* b, - std::vector& result) const { +template +void ViOperatorMultiplier::multiply(Environment const& env, std::vector const& x, + std::vector const* b, std::vector& result) const { if (&result == &x) { auto& tmpResult = this->provideCachedVector(x.size()); multiply(env, x, b, tmpResult); @@ -183,7 +183,7 @@ void ViOperatorMultiplier::multiply(Environment c return; } auto const& viOp = initialize(); - detail::PlainMultiplicationBackend backend(result); + detail::PlainMultiplicationBackend backend(result); // Below, we just add 'result' as a dummy argument to the apply method. // The backend already takes care of filling the result vector while processing the rows. if (b) { @@ -193,12 +193,12 @@ void ViOperatorMultiplier::multiply(Environment c } } -template -void ViOperatorMultiplier::multiplyGaussSeidel(Environment const& /*env*/, std::vector& x, - std::vector const* b, bool backwards) const { +template +void ViOperatorMultiplier::multiplyGaussSeidel(Environment const& /*env*/, std::vector& x, + std::vector const* b, bool backwards) const { STORM_LOG_THROW(TrivialRowGrouping, storm::exceptions::NotSupportedException, "This multiplier does not support multiplications without reduction when invoked with non-trivial row groups"); - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; auto const& viOp = initialize(backwards); if (b) { viOp.applyInPlace(x, *b, backend); @@ -207,11 +207,12 @@ void ViOperatorMultiplier::multiplyGaussSeidel(En } } -template -void ViOperatorMultiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, - std::vector const& rowGroupIndices, std::vector const& x, - std::vector const* b, std::vector& result, - std::vector* choices) const { +template +void ViOperatorMultiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, + std::vector const& rowGroupIndices, + std::vector const& x, std::vector const* b, + std::vector& result, + std::vector* choices) const { if (&result == &x) { auto& tmpResult = this->provideCachedVector(x.size()); multiplyAndReduce(env, dir, rowGroupIndices, x, b, tmpResult, choices); @@ -230,28 +231,27 @@ void ViOperatorMultiplier::multiplyAndReduce(Envi }; if (storm::solver::minimize(dir)) { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); apply(backend); } else { - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; apply(backend); } } else { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); apply(backend); } else { - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; apply(backend); } } } -template -void ViOperatorMultiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, - std::vector const& rowGroupIndices, std::vector& x, - std::vector const* b, std::vector* choices, - bool backwards) const { +template +void ViOperatorMultiplier::multiplyAndReduceGaussSeidel( + Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, + std::vector const* b, std::vector* choices, bool backwards) const { STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException, "The row group indices must be the same as the ones stored in the matrix of this multiplier"); auto const& viOp = initialize(backwards); @@ -264,28 +264,28 @@ void ViOperatorMultiplier::multiplyAndReduceGauss }; if (storm::solver::minimize(dir)) { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); apply(backend); } else { - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; apply(backend); } } else { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); apply(backend); } else { - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; apply(backend); } } } -template -void ViOperatorMultiplier::clearCache() const { +template +void ViOperatorMultiplier::clearCache() const { viOperatorBwd.reset(); viOperatorFwd.reset(); - Multiplier::clearCache(); + Multiplier::clearCache(); }; template class ViOperatorMultiplier; @@ -294,4 +294,10 @@ template class ViOperatorMultiplier; template class ViOperatorMultiplier; template class ViOperatorMultiplier; +template class ViOperatorMultiplier; +template class ViOperatorMultiplier; + +template class ViOperatorMultiplier; +template class ViOperatorMultiplier; + } // namespace storm::solver diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.h b/src/storm/solver/multiplier/ViOperatorMultiplier.h index 209ff9ee01..daeae609d3 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.h +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.h @@ -14,25 +14,26 @@ class SparseMatrix; namespace solver { -template -class ViOperatorMultiplier : public Multiplier { +template +class ViOperatorMultiplier : public Multiplier { public: ViOperatorMultiplier(storm::storage::SparseMatrix const& matrix); virtual ~ViOperatorMultiplier() = default; - virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, - std::vector& result) const override; - virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const override; + virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, + std::vector& result) const override; + virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, + bool backwards = true) const override; virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector const& x, std::vector const* b, std::vector& result, + std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const override; virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector& x, std::vector const* b, std::vector* choices = nullptr, + std::vector& x, std::vector const* b, std::vector* choices = nullptr, bool backwards = true) const override; virtual void clearCache() const override; private: - using ViOpT = storm::solver::helper::ValueIterationOperator; + using ViOpT = storm::solver::helper::ValueIterationOperator; ViOpT& initialize() const; ViOpT& initialize(bool backwards) const; diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 27a9254a16..00538c5113 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -124,7 +124,7 @@ TEST(RobustMDPModelCheckingTest, Tiny03maxmin) { } TEST(RobustMDPModelCheckingTest, BoundedTiny03maxmin) { - expectThrow(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"]"); + checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"]", 0.9, 0.9, 0.5, 0.4, true); } TEST(RobustMDPModelCheckingTest, Tiny04maxmin) { From 0d0269f6592bbfbe24e716c4153d106a24fb8dd9 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 10 Jul 2025 11:04:15 +0200 Subject: [PATCH 037/102] fix test of bounded until model checking --- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 00538c5113..7d3d4cbc0e 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -1,4 +1,6 @@ #include "storm-config.h" +#include "storm/adapters/RationalNumberForward.h" +#include "storm/exceptions/NotImplementedException.h" #include "test/storm_gtest.h" #include "storm-parsers/api/model_descriptions.h" @@ -24,6 +26,11 @@ std::unique_ptr getInitialStateFilt return std::make_unique(model->getInitialStates()); } +std::unique_ptr getInitialStateFilter( + std::shared_ptr> const& model) { + return std::make_unique(model->getInitialStates()); +} + double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, std::unique_ptr& result) { auto filter = getInitialStateFilter(model); @@ -38,6 +45,13 @@ double getQuantitativeResultAtInitialState(std::shared_ptrasQuantitativeCheckResult().getMin(); } +storm::RationalNumber getQuantitativeResultAtInitialState(std::shared_ptr> const& model, + std::unique_ptr& result) { + auto filter = getInitialStateFilter(model); + result->filter(*filter); + return result->asQuantitativeCheckResult().getMin(); +} + void expectThrow(std::string const& path, std::string const& formulaString) { std::shared_ptr> modelPtr = storm::parser::DirectEncodingParser::parseModel(path); std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); @@ -50,7 +64,7 @@ void expectThrow(std::string const& path, std::string const& formulaString) { auto task = storm::modelchecker::CheckTask(*formulas[0]); auto checker = storm::modelchecker::SparseMdpPrctlModelChecker>(*mdp); - STORM_SILENT_EXPECT_THROW(checker.check(env, task), storm::exceptions::InvalidArgumentException); + STORM_SILENT_EXPECT_THROW(checker.check(env, task), storm::exceptions::NotImplementedException); } void checkModel(std::string const& path, std::string const& formulaString, double maxmin, double maxmax, double minmax, double minmin, bool produceScheduler) { @@ -81,6 +95,36 @@ void checkModel(std::string const& path, std::string const& formulaString, doubl EXPECT_NEAR(minmin, getQuantitativeResultAtInitialState(mdp, resultMinNonRobust), 0.0001); } +void checkModelRational(std::string const& path, std::string const& formulaString, storm::RationalNumber maxmin, storm::RationalNumber maxmax, + storm::RationalNumber minmax, storm::RationalNumber minmin, bool produceScheduler) { + std::shared_ptr> modelPtr = + storm::parser::DirectEncodingParser::parseModel(path); + std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); + storm::Environment env; + env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); + + std::shared_ptr> mdp = modelPtr->as>(); + ASSERT_EQ(storm::models::ModelType::Mdp, modelPtr->getType()); + auto taskMax = storm::modelchecker::CheckTask(*formulas[0]); + taskMax.setProduceSchedulers(produceScheduler); + + auto checker = storm::modelchecker::SparseMdpPrctlModelChecker>(*mdp); + auto resultMax = checker.check(env, taskMax); + EXPECT_EQ(maxmin, getQuantitativeResultAtInitialState(mdp, resultMax)); + taskMax.setRobustUncertainty(false); + auto resultMaxNonRobust = checker.check(env, taskMax); + EXPECT_EQ(maxmax, getQuantitativeResultAtInitialState(mdp, resultMaxNonRobust)); + + auto taskMin = storm::modelchecker::CheckTask(*formulas[1]); + taskMin.setProduceSchedulers(produceScheduler); + + auto resultMin = checker.check(env, taskMin); + EXPECT_EQ(minmax, getQuantitativeResultAtInitialState(mdp, resultMin)); + taskMin.setRobustUncertainty(false); + auto resultMinNonRobust = checker.check(env, taskMin); + EXPECT_EQ(minmin, getQuantitativeResultAtInitialState(mdp, resultMinNonRobust)); +} + void makeUncertainAndCheck(std::string const& path, std::string const& formulaString, double amountOfUncertainty) { storm::prism::Program program = storm::api::parseProgram(path); program = storm::utility::prism::preprocess(program, ""); @@ -124,7 +168,9 @@ TEST(RobustMDPModelCheckingTest, Tiny03maxmin) { } TEST(RobustMDPModelCheckingTest, BoundedTiny03maxmin) { - checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"]", 0.9, 0.9, 0.5, 0.4, true); + checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.9, 0.9, 0.9, 0.9, true); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(9, 10), + storm::RationalNumber(9, 10), storm::RationalNumber(9, 10), storm::RationalNumber(9, 10), true); } TEST(RobustMDPModelCheckingTest, Tiny04maxmin) { From efabc1e0c68db8b79a491c424a77171c39c83b54 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 10 Jul 2025 14:50:29 +0200 Subject: [PATCH 038/102] fix initialization of submatrix and b --- ...ndeterministicStepBoundedHorizonHelper.cpp | 37 ++++++++++++++++--- .../solver/helper/ValueIterationOperator.h | 8 ++++ .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 6 +-- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp index d262dd609a..ffd8ef3628 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp @@ -6,6 +6,7 @@ #include "storm/models/sparse/StandardRewardModel.h" +#include "storm/storage/BitVector.h" #include "storm/utility/graph.h" #include "storm/utility/macros.h" #include "storm/utility/vector.h" @@ -56,19 +57,45 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false, makeZeroColumns); - std::vector b = transitionMatrix.getConstrainedRowGroupSumVector(maybeStates, psiStates); + storm::storage::SparseMatrix submatrix; + std::vector b; + uint64_t subresultSize; + + if constexpr (std::is_same_v || std::is_same_v) { + std::cout << "Chose interval branch" << std::endl; + // For intervals, we cannot remove all non maybe states as that would lead to the upper probability of rows summing to below 1. + // Instead we only drop all outgoing transitions of non maybe states. + // See src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp:624 for more details. + submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates)); + + storm::utility::vector::setAllValues(b, transitionMatrix.getRowFilter(psiStates)); + + subresultSize = transitionMatrix.getRowCount(); + } else { + // We can eliminate the rows and columns from the original transition probability matrix that have probability 0. + submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false, makeZeroColumns); + + b = transitionMatrix.getConstrainedRowGroupSumVector(maybeStates, psiStates); + subresultSize = maybeStates.getNumberOfSetBits(); + } // Create the vector with which to multiply. - std::vector subresult(maybeStates.getNumberOfSetBits()); + std::vector subresult(subresultSize); auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); if (lowerBound == 0) { multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound); } else { multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound - lowerBound + 1); - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); + + storm::storage::SparseMatrix submatrix; + if constexpr (std::is_same_v || std::is_same_v) { + std::cout << "Chose interval branch again" << std::endl; + submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates)); + } else { + submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); + } + auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); b = std::vector(b.size(), storm::utility::zero()); multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, lowerBound - 1); diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index 43803abb2f..5b51f52bd7 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -322,6 +323,8 @@ class ValueIterationOperator { STORM_LOG_ASSERT(*matrixColumnIt >= StartOfRowIndicator, "VI Operator in invalid state."); SolutionType result{robustInitializeRowRes(operand, offsets, offsetIndex)}; + std::cout << "Robust value iteration apply row robust start" << std::endl; + applyCache.robustOrder.clear(); if (applyCache.hasOnlyConstants.size() > 0 && applyCache.hasOnlyConstants.get(offsetIndex)) { @@ -341,6 +344,7 @@ class ValueIterationOperator { uint64_t orderCounter = 0; for (++matrixColumnIt; *matrixColumnIt < StartOfRowIndicator; ++matrixColumnIt, ++matrixValueIt, ++orderCounter) { SolutionType const lower = matrixValueIt->lower(); + std::cout << "Robust value iteration: lower = " << lower << std::endl; if constexpr (isPair::value) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Value Iteration is not implemented with pairs and interval-models."); // Notice the unclear semantics here in terms of how to order things. @@ -357,11 +361,15 @@ class ValueIterationOperator { return result; } + std::cout << "Robust value iteration: remaining value = " << remainingValue << std::endl; + static AuxCompare cmp; std::sort(applyCache.robustOrder.begin(), applyCache.robustOrder.end(), cmp); for (auto const& pair : applyCache.robustOrder) { SolutionType availableMass = std::min(pair.second.first, remainingValue); + std::cout << "Robust value iteration: available mass = " << availableMass << " for diameter " << pair.second.first << " and remaining value " + << remainingValue << std::endl; result += availableMass * pair.first; remainingValue -= availableMass; if (storm::utility::isZero(remainingValue)) { diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 7d3d4cbc0e..1d822feb0f 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -168,9 +168,9 @@ TEST(RobustMDPModelCheckingTest, Tiny03maxmin) { } TEST(RobustMDPModelCheckingTest, BoundedTiny03maxmin) { - checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.9, 0.9, 0.9, 0.9, true); - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(9, 10), - storm::RationalNumber(9, 10), storm::RationalNumber(9, 10), storm::RationalNumber(9, 10), true); + checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.5, 0.5, 0.5, 0.5, true); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(1, 2), + storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), true); } TEST(RobustMDPModelCheckingTest, Tiny04maxmin) { From 0bba8f6de58bb633ecfba1494eafa05c4c91db4d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 10 Jul 2025 14:59:09 +0200 Subject: [PATCH 039/102] remove prints --- .../SparseNondeterministicStepBoundedHorizonHelper.cpp | 2 -- src/storm/solver/helper/ValueIterationOperator.h | 7 ------- 2 files changed, 9 deletions(-) diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp index ffd8ef3628..b3739fe0c3 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp @@ -62,7 +62,6 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper || std::is_same_v) { - std::cout << "Chose interval branch" << std::endl; // For intervals, we cannot remove all non maybe states as that would lead to the upper probability of rows summing to below 1. // Instead we only drop all outgoing transitions of non maybe states. // See src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp:624 for more details. @@ -90,7 +89,6 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper submatrix; if constexpr (std::is_same_v || std::is_same_v) { - std::cout << "Chose interval branch again" << std::endl; submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates)); } else { submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index 5b51f52bd7..be062f1501 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -323,8 +323,6 @@ class ValueIterationOperator { STORM_LOG_ASSERT(*matrixColumnIt >= StartOfRowIndicator, "VI Operator in invalid state."); SolutionType result{robustInitializeRowRes(operand, offsets, offsetIndex)}; - std::cout << "Robust value iteration apply row robust start" << std::endl; - applyCache.robustOrder.clear(); if (applyCache.hasOnlyConstants.size() > 0 && applyCache.hasOnlyConstants.get(offsetIndex)) { @@ -344,7 +342,6 @@ class ValueIterationOperator { uint64_t orderCounter = 0; for (++matrixColumnIt; *matrixColumnIt < StartOfRowIndicator; ++matrixColumnIt, ++matrixValueIt, ++orderCounter) { SolutionType const lower = matrixValueIt->lower(); - std::cout << "Robust value iteration: lower = " << lower << std::endl; if constexpr (isPair::value) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Value Iteration is not implemented with pairs and interval-models."); // Notice the unclear semantics here in terms of how to order things. @@ -361,15 +358,11 @@ class ValueIterationOperator { return result; } - std::cout << "Robust value iteration: remaining value = " << remainingValue << std::endl; - static AuxCompare cmp; std::sort(applyCache.robustOrder.begin(), applyCache.robustOrder.end(), cmp); for (auto const& pair : applyCache.robustOrder) { SolutionType availableMass = std::min(pair.second.first, remainingValue); - std::cout << "Robust value iteration: available mass = " << availableMass << " for diameter " << pair.second.first << " and remaining value " - << remainingValue << std::endl; result += availableMass * pair.first; remainingValue -= availableMass; if (storm::utility::isZero(remainingValue)) { From b3f6b9069996418ffb7290c2347e01e4fa13e8c8 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 23 Jul 2025 19:21:55 +0200 Subject: [PATCH 040/102] Make interval optimization direction opposite of non-det opt. dir. --- .../multiplier/ViOperatorMultiplier.cpp | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp index e3011fb094..c90b329d58 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp @@ -2,6 +2,7 @@ #include "storm/adapters/RationalNumberAdapter.h" #include "storm/adapters/RationalNumberForward.h" +#include "storm/solver/OptimizationDirection.h" #include "storm/solver/helper/ValueIterationOperator.h" #include "storm/storage/SparseMatrix.h" @@ -222,28 +223,36 @@ void ViOperatorMultiplier::multiply STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException, "The row group indices must be the same as the ones stored in the matrix of this multiplier"); auto const& viOp = initialize(); - auto apply = [&](BT& backend) { - if (b) { - viOp.apply(x, result, *b, backend); + auto apply = [&](BT& backend, OptimizationDirection od) { + if (od == OptimizationDirection::Minimize) { + if (b) { + viOp.template applyRobust(x, result, *b, backend); + } else { + viOp.template applyRobust(x, result, storm::utility::zero(), backend); + } } else { - viOp.apply(x, result, storm::utility::zero(), backend); + if (b) { + viOp.template applyRobust(x, result, *b, backend); + } else { + viOp.template applyRobust(x, result, storm::utility::zero(), backend); + } } }; if (storm::solver::minimize(dir)) { if (choices) { detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend); + apply(backend, OptimizationDirection::Maximize); } else { detail::MultiplierBackend backend; - apply(backend); + apply(backend, OptimizationDirection::Maximize); } } else { if (choices) { detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend); + apply(backend, OptimizationDirection::Minimize); } else { detail::MultiplierBackend backend; - apply(backend); + apply(backend, OptimizationDirection::Minimize); } } } From d9d351f7d1430f86e481da58cf7468441eecd4bb Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 1 Sep 2025 15:55:54 +0200 Subject: [PATCH 041/102] merge fix --- src/storm/storage/BitVector.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/storm/storage/BitVector.h b/src/storm/storage/BitVector.h index 12d135f6a6..28e9c67d86 100644 --- a/src/storm/storage/BitVector.h +++ b/src/storm/storage/BitVector.h @@ -596,11 +596,6 @@ class BitVector { */ bool hasUniqueSetBit() const; - /* - * @return True, if the number of set bits is 1, false otherwise. - */ - bool hasUniqueSetBit() const; - /*! * Retrieves the number of bits this bit vector can store. * From 33887a81e12991ad1200bbf8492884de55242707 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 16 Sep 2025 10:22:12 +0200 Subject: [PATCH 042/102] Fix conditional model checking bugs --- .../helper/conditional/ConditionalHelper.cpp | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 1d36640485..7376686b7c 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -588,14 +588,24 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b } // update middle to the average of the bounds, but scale it according to the middle value (which is in [-1,1]) middle = *lowerBound + (storm::utility::one() + middleValue) * (*upperBound - *lowerBound) / 2; - STORM_LOG_ASSERT(middle >= *lowerBound && middle <= *upperBound, "Bisection method bounds are inconsistent."); + + if (!storm::NumberTraits::IsExact && storm::utility::isAlmostZero(*upperBound - *lowerBound)) { + if (*lowerBound > *upperBound) { + std::swap(*lowerBound, *upperBound); + } + STORM_LOG_WARN("Precision of non-exact type reached during bisection method. Result might be inaccurate."); + } else { + STORM_LOG_ASSERT(middle >= *lowerBound && middle <= *upperBound, "Bisection method bounds are inconsistent."); + } } // check for convergence SolutionType const boundDiff = *upperBound - *lowerBound; - STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) - << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) - << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) - << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "."); + STORM_LOG_TRACE("Iteration #" << iterationCount + << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) + << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) + << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) + << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) + << ",\n\t Difference bound: " << storm::utility::convertNumber((relative ? (precision * *lowerBound) : precision)) << "."); if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " << std::setprecision(std::numeric_limits::digits10) @@ -612,8 +622,15 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b if constexpr (storm::NumberTraits::IsExact) { // find a rational number with a concise representation close to middle and within the bounds auto const exactMiddle = middle; - auto numDigits = storm::utility::convertNumber( - storm::utility::floor(storm::utility::log10(storm::utility::one() / (*upperBound - *lowerBound)))); + + // Find number of digits - 1. Method using log10 does not work since that uses doubles internally. + auto numDigits = -1; + SolutionType remaining = storm::utility::one() / (*upperBound - *lowerBound); + while (remaining >= storm::utility::one()) { + ++numDigits; + remaining = storm::utility::floor(remaining / storm::utility::convertNumber(10)); + } + do { ++numDigits; middle = storm::utility::kwek_mehlhorn::sharpen(numDigits, exactMiddle); From 1eaebdfd92d122cde457066f8145ffb3ea30aa59 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 16 Sep 2025 10:22:12 +0200 Subject: [PATCH 043/102] Fix conditional model checking bugs --- .../helper/conditional/ConditionalHelper.cpp | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 1d36640485..7376686b7c 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -588,14 +588,24 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b } // update middle to the average of the bounds, but scale it according to the middle value (which is in [-1,1]) middle = *lowerBound + (storm::utility::one() + middleValue) * (*upperBound - *lowerBound) / 2; - STORM_LOG_ASSERT(middle >= *lowerBound && middle <= *upperBound, "Bisection method bounds are inconsistent."); + + if (!storm::NumberTraits::IsExact && storm::utility::isAlmostZero(*upperBound - *lowerBound)) { + if (*lowerBound > *upperBound) { + std::swap(*lowerBound, *upperBound); + } + STORM_LOG_WARN("Precision of non-exact type reached during bisection method. Result might be inaccurate."); + } else { + STORM_LOG_ASSERT(middle >= *lowerBound && middle <= *upperBound, "Bisection method bounds are inconsistent."); + } } // check for convergence SolutionType const boundDiff = *upperBound - *lowerBound; - STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) - << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) - << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) - << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << "."); + STORM_LOG_TRACE("Iteration #" << iterationCount + << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) + << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) + << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) + << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) + << ",\n\t Difference bound: " << storm::utility::convertNumber((relative ? (precision * *lowerBound) : precision)) << "."); if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " << std::setprecision(std::numeric_limits::digits10) @@ -612,8 +622,15 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b if constexpr (storm::NumberTraits::IsExact) { // find a rational number with a concise representation close to middle and within the bounds auto const exactMiddle = middle; - auto numDigits = storm::utility::convertNumber( - storm::utility::floor(storm::utility::log10(storm::utility::one() / (*upperBound - *lowerBound)))); + + // Find number of digits - 1. Method using log10 does not work since that uses doubles internally. + auto numDigits = -1; + SolutionType remaining = storm::utility::one() / (*upperBound - *lowerBound); + while (remaining >= storm::utility::one()) { + ++numDigits; + remaining = storm::utility::floor(remaining / storm::utility::convertNumber(10)); + } + do { ++numDigits; middle = storm::utility::kwek_mehlhorn::sharpen(numDigits, exactMiddle); From c4564d4786757239685b326398fac4cec16c2ef2 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 16 Sep 2025 10:26:54 +0200 Subject: [PATCH 044/102] add warning to gmp log10 --- src/storm/utility/constants.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index 7a02247711..0390174d48 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -12,6 +12,7 @@ #include "storm/utility/NumberTraits.h" #include "storm/exceptions/NotSupportedException.h" +#include "storm/utility/logging.h" #include "storm/utility/macros.h" namespace storm { @@ -641,6 +642,7 @@ GmpRationalNumber log(GmpRationalNumber const& number) { template<> GmpRationalNumber log10(GmpRationalNumber const& number) { + STORM_LOG_WARN("Using log10 for GMP rational numbers is not exact, it converts to doubles internally."); return carl::log10(number); } From 2cd0c932dadbd63e297f038efc69a045fe148134 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 16 Sep 2025 10:32:14 +0200 Subject: [PATCH 045/102] improve warning --- src/storm/utility/constants.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index 0390174d48..46d1450c73 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -642,7 +642,7 @@ GmpRationalNumber log(GmpRationalNumber const& number) { template<> GmpRationalNumber log10(GmpRationalNumber const& number) { - STORM_LOG_WARN("Using log10 for GMP rational numbers is not exact, it converts to doubles internally."); + STORM_LOG_WARN("Using log10 for GMP rational numbers is not exact, it converts to doubles internally! Avoid if possible."); return carl::log10(number); } From c3ecc83cae4b8ea2bc38dddbafd68b33f0dcb521 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 16 Sep 2025 10:36:37 +0200 Subject: [PATCH 046/102] fix formatting --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 7376686b7c..90808958d2 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -600,12 +600,11 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b } // check for convergence SolutionType const boundDiff = *upperBound - *lowerBound; - STORM_LOG_TRACE("Iteration #" << iterationCount - << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) + STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) - << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) - << ",\n\t Difference bound: " << storm::utility::convertNumber((relative ? (precision * *lowerBound) : precision)) << "."); + << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << ",\n\t Difference bound: " + << storm::utility::convertNumber((relative ? (precision * *lowerBound) : precision)) << "."); if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " << std::setprecision(std::numeric_limits::digits10) From 27020c9f59a3797334298ccad54759292e80aca2 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 17 Sep 2025 10:49:25 +0200 Subject: [PATCH 047/102] create numDigits function --- .../helper/conditional/ConditionalHelper.cpp | 7 +------ src/storm/utility/constants.cpp | 16 ++++++++++++++++ src/storm/utility/constants.h | 5 +++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 90808958d2..fe56d23ba9 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -623,12 +623,7 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b auto const exactMiddle = middle; // Find number of digits - 1. Method using log10 does not work since that uses doubles internally. - auto numDigits = -1; - SolutionType remaining = storm::utility::one() / (*upperBound - *lowerBound); - while (remaining >= storm::utility::one()) { - ++numDigits; - remaining = storm::utility::floor(remaining / storm::utility::convertNumber(10)); - } + auto numDigits = storm::utility::numDigits(*upperBound - *lowerBound) - 1; do { ++numDigits; diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index 46d1450c73..1318962903 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -1,8 +1,10 @@ #include "storm/utility/constants.h" #include +#include #include +#include "storm/adapters/RationalNumberAdapter.h" #include "storm/storage/sparse/StateType.h" #include "storm/exceptions/InvalidArgumentException.h" @@ -264,6 +266,18 @@ ValueType sin(ValueType const& number) { return std::sin(number); } +template +uint64_t numDigits(ValueType const& number) { + auto numDigits = 0; + ValueType remaining = storm::utility::one() / number; + ValueType ten = storm::utility::convertNumber(10); + while (remaining >= storm::utility::one()) { + ++numDigits; + remaining = storm::utility::floor(remaining / ten); + } + return numDigits; +} + template typename NumberTraits::IntegerType trunc(ValueType const& number) { return static_cast::IntegerType>(std::trunc(number)); @@ -1067,6 +1081,7 @@ template storm::ClnRationalNumber max(storm::ClnRationalNumber const& first, sto template storm::ClnRationalNumber min(storm::ClnRationalNumber const& first, storm::ClnRationalNumber const& second); template storm::ClnRationalNumber round(storm::ClnRationalNumber const& number); template std::string to_string(storm::ClnRationalNumber const& value); +template uint64_t numDigits(const storm::ClnRationalNumber& number); #endif #if defined(STORM_HAVE_GMP) @@ -1091,6 +1106,7 @@ template storm::GmpRationalNumber max(storm::GmpRationalNumber const& first, sto template storm::GmpRationalNumber min(storm::GmpRationalNumber const& first, storm::GmpRationalNumber const& second); template storm::GmpRationalNumber round(storm::GmpRationalNumber const& number); template std::string to_string(storm::GmpRationalNumber const& value); +template uint64_t numDigits(const storm::GmpRationalNumber& number); #endif #if defined(STORM_HAVE_CARL) && defined(STORM_HAVE_GMP) && defined(STORM_HAVE_CLN) diff --git a/src/storm/utility/constants.h b/src/storm/utility/constants.h index 4fce01d485..49e0ebe998 100644 --- a/src/storm/utility/constants.h +++ b/src/storm/utility/constants.h @@ -1,6 +1,8 @@ #ifndef STORM_UTILITY_CONSTANTS_H_ #define STORM_UTILITY_CONSTANTS_H_ +#include +#include #ifdef max #undef max #endif @@ -173,6 +175,9 @@ ValueType cos(ValueType const& number); template ValueType sin(ValueType const& number); +template +uint64_t numDigits(ValueType const& number); + template typename NumberTraits::IntegerType trunc(ValueType const& number); From fe180ccc04840ed5c7eed8da85016bed27fa5043 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 17 Sep 2025 10:55:17 +0200 Subject: [PATCH 048/102] remove accidental imports --- src/storm/utility/constants.cpp | 2 -- src/storm/utility/constants.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index 1318962903..70a951e680 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -1,10 +1,8 @@ #include "storm/utility/constants.h" #include -#include #include -#include "storm/adapters/RationalNumberAdapter.h" #include "storm/storage/sparse/StateType.h" #include "storm/exceptions/InvalidArgumentException.h" diff --git a/src/storm/utility/constants.h b/src/storm/utility/constants.h index 49e0ebe998..5bff116c7e 100644 --- a/src/storm/utility/constants.h +++ b/src/storm/utility/constants.h @@ -1,8 +1,6 @@ #ifndef STORM_UTILITY_CONSTANTS_H_ #define STORM_UTILITY_CONSTANTS_H_ -#include -#include #ifdef max #undef max #endif From 3f543ee718b1b4178f72d56664183ad13960c1f1 Mon Sep 17 00:00:00 2001 From: Filip Macak Date: Wed, 5 Nov 2025 15:53:52 +0100 Subject: [PATCH 049/102] Added support for exporting scheduler for conditional properties --- src/storm/modelchecker/CheckTask.h | 50 +- .../helper/conditional/ConditionalHelper.cpp | 487 ++++++++++++++++-- .../helper/conditional/ConditionalHelper.h | 3 + .../prctl/SparseMdpPrctlModelChecker.cpp | 2 +- src/storm/storage/Scheduler.cpp | 20 + src/storm/storage/Scheduler.h | 12 + 6 files changed, 528 insertions(+), 46 deletions(-) diff --git a/src/storm/modelchecker/CheckTask.h b/src/storm/modelchecker/CheckTask.h index 8804b64a3d..ab7b845684 100644 --- a/src/storm/modelchecker/CheckTask.h +++ b/src/storm/modelchecker/CheckTask.h @@ -11,6 +11,7 @@ #include "storm/logic/PlayerCoalition.h" #include "storm/modelchecker/hints/ModelCheckerHint.h" #include "storm/solver/OptimizationDirection.h" +#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/exceptions/InvalidOperationException.h" @@ -52,7 +53,7 @@ class CheckTask { CheckTask substituteFormula(NewFormulaType const& newFormula) const { CheckTask result(newFormula, this->optimizationDirection, this->playerCoalition, this->rewardModel, this->onlyInitialStatesRelevant, this->bound, this->qualitative, this->produceSchedulers, this->hint, - this->robustUncertainty); + this->robustUncertainty, this->reachConditionalStatesResult, this->reachTargetStatesResult); result.updateOperatorInformation(); return result; } @@ -129,9 +130,12 @@ class CheckTask { */ template CheckTask convertValueType() const { - return CheckTask(this->formula, this->optimizationDirection, this->playerCoalition, this->rewardModel, - this->onlyInitialStatesRelevant, this->bound, this->qualitative, this->produceSchedulers, this->hint, - this->robustUncertainty); + + return CheckTask(this->formula, this->optimizationDirection, this->playerCoalition, this->rewardModel, this->onlyInitialStatesRelevant, + this->bound, this->qualitative, this->produceSchedulers, this->hint, this->robustUncertainty, + this->reachConditionalStatesResult, this->reachTargetStatesResult + ); + } /*! @@ -313,6 +317,30 @@ class CheckTask { robustUncertainty = robust; } + void setReachConditionalStatesResult(std::tuple, std::vector> const& result) { + reachConditionalStatesResult = result; + } + + bool hasReachConditionalStatesResult() const { + return static_cast(reachConditionalStatesResult); + } + + std::tuple, std::vector> const& getReachConditionalStatesResult() const { + return reachConditionalStatesResult.get(); + } + + void setReachTargetStatesResult(std::tuple, std::vector> const& result) { + reachTargetStatesResult = result; + } + + bool hasReachTargetStatesResult() const { + return static_cast(reachTargetStatesResult); + } + + std::tuple, std::vector> const& getReachTargetStatesResult() const { + return reachTargetStatesResult.get(); + } + private: /*! * Creates a task object with the given options. @@ -332,7 +360,8 @@ class CheckTask { CheckTask(std::reference_wrapper const& formula, boost::optional const& optimizationDirection, boost::optional playerCoalition, boost::optional const& rewardModel, bool onlyInitialStatesRelevant, boost::optional const& bound, bool qualitative, bool produceSchedulers, std::shared_ptr const& hint, - bool robust) + bool robust, boost::optional, std::vector>> const& reachConditionalStatesResult, + boost::optional, std::vector>> const& reachTargetStatesResult) : formula(formula), optimizationDirection(optimizationDirection), playerCoalition(playerCoalition), @@ -342,7 +371,9 @@ class CheckTask { qualitative(qualitative), produceSchedulers(produceSchedulers), hint(hint), - robustUncertainty(robust) { + robustUncertainty(robust), + reachConditionalStatesResult(reachConditionalStatesResult), + reachTargetStatesResult(reachTargetStatesResult) { // Intentionally left empty. } @@ -374,6 +405,13 @@ class CheckTask { // A hint that might contain information that speeds up the modelchecking process (if supported by the model checker) std::shared_ptr hint; + // TODO I'm not sure if these should be templated or not + // If set, the result will be used for conditional states in model checking of conditional properties. + boost::optional, std::vector>> reachConditionalStatesResult; + + // If set, the result will be used for target states in model checking of conditional properties. + boost::optional, std::vector>> reachTargetStatesResult; + /// Whether uncertainty should be resolved robust (standard) or angelically. bool robustUncertainty; }; diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index fe56d23ba9..6df56a96b8 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -19,6 +19,8 @@ #include "storm/utility/graph.h" #include "storm/utility/macros.h" +#include "storm/modelchecker/prctl/helper/MDPModelCheckingHelperReturnType.h" + #include "storm/exceptions/NotImplementedException.h" #include "storm/exceptions/NotSupportedException.h" @@ -27,12 +29,12 @@ namespace storm::modelchecker { namespace internal { template -void eliminateEndComponents(storm::storage::BitVector possibleEcStates, bool addRowAtRepresentativeState, std::optional representativeRowEntry, +boost::optional::EndComponentEliminatorReturnType> eliminateEndComponents(storm::storage::BitVector possibleEcStates, bool addRowAtRepresentativeState, std::optional representativeRowEntry, storm::storage::SparseMatrix& matrix, uint64_t& initialState, storm::storage::BitVector& rowsWithSum1, std::vector& rowValues1, storm::OptionalRef> rowValues2 = {}) { storm::storage::MaximalEndComponentDecomposition ecs(matrix, matrix.transpose(true), possibleEcStates, rowsWithSum1); if (ecs.empty()) { - return; // nothing to do + return boost::none; // nothing to do } storm::storage::BitVector allRowGroups(matrix.getRowGroupCount(), true); @@ -81,10 +83,26 @@ void eliminateEndComponents(storm::storage::BitVector possibleEcStates, bool add ++newRowIndex; } rowsWithSum1 = std::move(newRowsWithSum1); + + return ecElimResult; } +template +struct SolverResult { + SolverResult(ValueType initialStateValue) : initialStateValue(initialStateValue) { + // Intentionally left empty. + } + + bool hasScheduler() const { + return static_cast(scheduler); + } + + ValueType initialStateValue; + boost::optional> scheduler; +}; + template -SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, +typename internal::SolverResult solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, storm::solver::OptimizationDirection const dir, uint64_t const initialState) { // Initialize the solution vector. @@ -98,10 +116,15 @@ SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::sto solver->setHasNoEndComponents(true); solver->setLowerBound(storm::utility::zero()); solver->setUpperBound(storm::utility::one()); + solver->setTrackScheduler(true); // Solve the corresponding system of equations. solver->solveEquations(env, x, rowValues); - return x[initialState]; + + SolverResult result(x[initialState]); + result.scheduler = std::move(solver->getSchedulerChoices()); + + return result; } /*! @@ -125,7 +148,7 @@ void computeReachabilityProbabilities(Environment const& env, std::map::computeUntilProbabilities( env, storm::solver::SolveGoal(dir, subInits), submatrix, submatrix.transpose(true), storm::storage::BitVector(subTargets.size(), true), - subTargets, false, false); + subTargets, false, true); auto origInitIt = initialStates.begin(); for (auto subInit : subInits) { auto const& val = subResult.values[subInit]; @@ -136,11 +159,64 @@ void computeReachabilityProbabilities(Environment const& env, std::map +std::unique_ptr> computeReachabilityProbabilitiesAndScheduler(Environment const& env, + std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, + storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { + if (initialStates.empty()) { // nothing to do + return nullptr; + } + + auto result = helper::SparseMdpPrctlHelper::computeUntilProbabilities( + env, storm::solver::SolveGoal(dir, initialStates), transitionMatrix, transitionMatrix.transpose(true), storm::storage::BitVector(targetStates.size(), true), + targetStates, false, true); + for (auto initState : initialStates) { + auto const& val = result.values[initState]; + if (!storm::utility::isZero(val)) { + nonZeroResults.emplace(initState, val); + } + } + + return std::move(result.scheduler); +} + +/*! + * Uses the precomputed the reachability probabilities for the given target states and inserts all non-zero values into the given map. + * @note This code is optimized for cases where not all states are reachable from the initial states. + */ +template +void computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, + storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates, std::vector const& precomputedReachProbs) { + if (initialStates.empty()) { // nothing to do + return; + } + auto const reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, allowedStates, targetStates); + auto const subTargets = targetStates % reachableStates; + // Catch the case where no target is reachable from an initial state. In this case, there is nothing to do since all probabilities are zero. + if (subTargets.empty()) { + return; + } + + for (auto initState : initialStates) { + auto const& val = precomputedReachProbs[initState]; + if (!storm::utility::isZero(val)) { + nonZeroResults.emplace(initState, val); + } + } +} + template struct NormalFormData { storm::storage::BitVector const maybeStates; // Those states that can be reached from initial without reaching a terminal state storm::storage::BitVector const terminalStates; // Those states where we already know the probability to reach the condition and the target value storm::storage::BitVector const conditionStates; // Those states where the condition holds almost surely (under all schedulers) + storm::storage::BitVector const targetStates; // Those states where the target holds almost surely (under all schedulers) storm::storage::BitVector const universalObservationFailureStates; // Those states where the condition is not reachable (under all schedulers) storm::storage::BitVector const existentialObservationFailureStates; // Those states s where a scheduler exists that (i) does not reach the condition from // s and (ii) acts optimal in all terminal states @@ -154,6 +230,9 @@ struct NormalFormData { // TerminalStates is a superset of conditionStates and dom(nonZeroTargetStateValues). // For a terminalState that is not a conditionState, it is impossible to (reach the condition and not reach the target). + std::vector const schedulerChoicesForReachingTargetStates; // Scheduler choices for reaching target states, used for constructing the resulting scheduler + std::vector const schedulerChoicesForReachingConditionStates; // Scheduler choices for reaching condition states, used for constructing the resulting scheduler + ValueType getTargetValue(uint64_t state) const { STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get target value for non-terminal state"); auto const it = nonZeroTargetStateValues.find(state); @@ -172,7 +251,8 @@ template NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& relevantStates, - storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, + storm::modelchecker::CheckTask const& checkTask) { storm::storage::BitVector const allStates(transitionMatrix.getRowGroupCount(), true); auto extendedConditionStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); @@ -180,9 +260,44 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver std::map nonZeroTargetStateValues; auto const extendedTargetStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, targetStates); - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates); - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + + std::vector schedulerChoicesForReachingTargetStates; + std::vector schedulerChoicesForReachingConditionStates; + + if (!checkTask.isProduceSchedulersSet()) { + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + } else { + // if produce scheduler is set, we need to store the choices scheduler makes after reaching the condition or target state + if (checkTask.hasReachTargetStatesResult()) { + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates, + std::get<0>(checkTask.getReachTargetStatesResult())); + schedulerChoicesForReachingTargetStates = std::get<1>(checkTask.getReachTargetStatesResult()); + } else { + auto scheduler = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); + schedulerChoicesForReachingTargetStates = std::vector(transitionMatrix.getRowGroupCount(), 0); + if (scheduler) { + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + schedulerChoicesForReachingTargetStates[state] = scheduler->getChoice(state).getDeterministicChoice(); + } + } + } + + if (checkTask.hasReachConditionalStatesResult()) { + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates, + std::get<0>(checkTask.getReachConditionalStatesResult())); + schedulerChoicesForReachingConditionStates = std::get<1>(checkTask.getReachConditionalStatesResult()); + } else { + auto scheduler = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + schedulerChoicesForReachingConditionStates = std::vector(transitionMatrix.getRowGroupCount(), 0); + if (scheduler) { + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + schedulerChoicesForReachingConditionStates[state] = scheduler->getChoice(state).getDeterministicChoice(); + } + } + } + } // get states where the optimal policy reaches the condition with positive probability auto terminalStatesThatReachCondition = extendedConditionStates; @@ -213,18 +328,67 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver return NormalFormData{.maybeStates = std::move(nonTerminalStates), .terminalStates = std::move(terminalStates), .conditionStates = std::move(extendedConditionStates), + .targetStates = std::move(extendedTargetStates), .universalObservationFailureStates = std::move(universalObservationFailureStates), .existentialObservationFailureStates = std::move(existentialObservationFailureStates), - .nonZeroTargetStateValues = std::move(nonZeroTargetStateValues)}; + .nonZeroTargetStateValues = std::move(nonZeroTargetStateValues), + .schedulerChoicesForReachingTargetStates = std::move(schedulerChoicesForReachingTargetStates), + .schedulerChoicesForReachingConditionStates = std::move(schedulerChoicesForReachingConditionStates)}; } +// computes the scheduler that reaches the EC exits from the maybe states that were removed by EC elimination +template +void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& scheduler, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, + storm::storage::BitVector const& maybeStatesWithoutChoice, storm::storage::BitVector const& maybeStatesWithChoice, + std::vector const& stateToFinalEc) { + + // Compute the EC stay choices for the states in maybeStatesWithChoice + storm::storage::BitVector ecStayChoices(transitionMatrix.getRowCount(), false); + + for (auto state : maybeStates) { + auto ecIndex = stateToFinalEc[state]; + for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { + bool isEcStayChoice = true; + for (auto const& entry : transitionMatrix.getRow(choiceIndex)) { + auto targetState = entry.getColumn(); + if (stateToFinalEc[targetState] != ecIndex) { + isEcStayChoice = false; + break; + } + } + if (isEcStayChoice) { + ecStayChoices.set(choiceIndex, true); + } + } + } + + storm::utility::graph::computeSchedulerProb1E(maybeStates, transitionMatrix, backwardTransitions, maybeStatesWithoutChoice, maybeStatesWithChoice, + scheduler, ecStayChoices); +} + +template +struct ResultReturnType { + ResultReturnType(ValueType initialStateValue, std::unique_ptr>&& scheduler = nullptr) : initialStateValue(initialStateValue), scheduler(std::move(scheduler)) { + // Intentionally left empty. + } + + bool hasScheduler() const { + return static_cast(scheduler); + } + + ValueType initialStateValue; + std::unique_ptr> scheduler; +}; + /*! * Uses the restart method by Baier et al. // @see doi.org/10.1007/978-3-642-54862-8_43 */ template -SolutionType computeViaRestartMethod(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { +typename internal::ResultReturnType computeViaRestartMethod(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, + NormalFormData const& normalForm) { auto const& maybeStates = normalForm.maybeStates; auto const stateToMatrixIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); auto const numMaybeStates = maybeStates.getNumberOfSetBits(); @@ -283,7 +447,8 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init } } - auto matrix = matrixBuilder.build(); + auto maybeMatrix = matrixBuilder.build(); + auto matrix = storm::storage::SparseMatrix(maybeMatrix); auto initStateInMatrix = stateToMatrixIndexMap[initialState]; // Eliminate end components in two phases @@ -291,16 +456,74 @@ SolutionType computeViaRestartMethod(Environment const& env, uint64_t const init // without reaching the condition. This is reflected by a backloop to the initial state. storm::storage::BitVector selectedStatesInMatrix(numMaybeStates, true); selectedStatesInMatrix.set(initStateInMatrix, false); - eliminateEndComponents(selectedStatesInMatrix, true, initStateInMatrix, matrix, initStateInMatrix, rowsWithSum1, rowValues); + auto ecElimResult1 = eliminateEndComponents(selectedStatesInMatrix, true, initStateInMatrix, matrix, initStateInMatrix, rowsWithSum1, rowValues); // Second, eliminate the remaining ECs. These must involve the initial state and might have been introduced in the previous step. // A policy selecting such an EC must reach the condition with probability zero and is thus invalid. selectedStatesInMatrix.set(initStateInMatrix, true); - eliminateEndComponents(selectedStatesInMatrix, false, std::nullopt, matrix, initStateInMatrix, rowsWithSum1, rowValues); + auto ecElimResult2 = eliminateEndComponents(selectedStatesInMatrix, false, std::nullopt, matrix, initStateInMatrix, rowsWithSum1, rowValues); STORM_LOG_INFO("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " << matrix.getEntryCount() << " transitions."); // Finally, solve the equation system - return solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); + auto result = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); + + // std::vector finalSchedulerChoices(transitionMatrix.getRowGroupCount(), -1); + storm::storage::BitVector maybeStatesWithChoice(maybeStates.size(), false); + std::unique_ptr> scheduler; + scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + // std::vector ecsToExits(matrix.getRowGroupCount(), 0); + if (result.hasScheduler()) { + uint64_t state = 0; + for (auto& choice : *result.scheduler) { + uint64_t firstRowIndex = matrix.getRowGroupIndices()[state]; + uint64_t originalChoice = firstRowIndex + choice; + if (ecElimResult2.has_value()) { + originalChoice = ecElimResult2->newToOldRowMapping[originalChoice]; + } + if (ecElimResult1.has_value()) { + originalChoice = ecElimResult1->newToOldRowMapping[originalChoice]; + } + + uint64_t originalState; + auto const rowGroups = maybeMatrix.getRowGroupIndices(); + for (originalState = 0; originalState < maybeMatrix.getRowGroupCount(); ++originalState) { + auto const firstRowStateIndex = rowGroups[originalState+1]; + if (firstRowStateIndex > originalChoice) { + originalChoice = originalChoice - rowGroups[originalState]; + break; + } + } + + uint64_t index = 0; + for (uint64_t s = 0; s < originalState; ++s) { + index = maybeStates.getNextSetIndex(index+1); + } + + originalState = index; + // finalSchedulerChoices[originalState] = originalChoice; + scheduler->setChoice(originalChoice, originalState); + maybeStatesWithChoice.set(originalState, true); + // ecsToExits[state] = originalState; + ++state; + } + } + + std::vector stateToFinalEc(transitionMatrix.getRowGroupCount(), -1); + uint64_t state = 0; + for (auto s : maybeStates) { + auto mappedState = state; + mappedState = ecElimResult1.has_value() ? ecElimResult1->oldToNewStateMapping[mappedState] : mappedState; + mappedState = ecElimResult2.has_value() ? ecElimResult2->oldToNewStateMapping[mappedState] : mappedState; + stateToFinalEc[s] = mappedState; + state++; + } + + auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, stateToFinalEc); + + auto finalResult = ResultReturnType(result.initialStateValue, std::move(scheduler)); + + return finalResult; } /*! @@ -341,6 +564,7 @@ class WeightedReachabilityHelper { } } } else { + initialComponentExitToOriginalRow.push_back(rowIndex); initialComponentExitRows.set(rowIndex, true); } } @@ -419,19 +643,39 @@ class WeightedReachabilityHelper { } } } - submatrix = matrixBuilder.build(); + fullSubmatrix = matrixBuilder.build(); + submatrix = storm::storage::SparseMatrix(fullSubmatrix); // eliminate ECs if present. We already checked that the initial state can not yield observation failure, so it cannot be part of an EC. // For all remaining ECs, staying in an EC forever is reflected by collecting a value of zero for both, target and condition storm::storage::BitVector allExceptInit(numSubmatrixRowGroups, true); allExceptInit.set(initialStateInSubmatrix, false); - eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, - conditionRowValues); + ecResult = eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, conditionRowValues); STORM_LOG_INFO("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " << submatrix.getEntryCount() << " transitions."); + + // if (ecElimResult.has_value()) { + // ecResult = std::make_unique::EndComponentEliminatorReturnType>(std::move(*ecElimResult)); + // } + + stateToFinalEc.resize(transitionMatrix.getRowGroupCount(), -1); + auto maybeStatesNotInSubmatrix = normalForm.maybeStates & ~subMatrixRowGroups; + + for (auto state : maybeStatesNotInSubmatrix) { + stateToFinalEc[state] = 0; + } + + uint64_t state = 0; + for (auto s : subMatrixRowGroups) { + uint64_t mappedState = state; + mappedState = ecResult.has_value() ? ecResult->oldToNewStateMapping[mappedState] : mappedState; + stateToFinalEc[s] = mappedState; + state++; + } + } - SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, + internal::SolverResult computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, ValueType const& conditionWeight) const { auto rowValues = createScaledVector(targetWeight, targetRowValues, conditionWeight, conditionRowValues); @@ -446,9 +690,15 @@ class WeightedReachabilityHelper { solver->setHasNoEndComponents(true); solver->setLowerBound(-storm::utility::one()); solver->setUpperBound(storm::utility::one()); + solver->setTrackScheduler(true); + // Solve the corresponding system of equations. solver->solveEquations(env, x, rowValues); - return x[initialStateInSubmatrix]; + + SolverResult result(x[initialStateInSubmatrix]); + result.scheduler = std::move(solver->getSchedulerChoices()); + + return result; } auto getInternalInitialState() const { @@ -513,6 +763,12 @@ class WeightedReachabilityHelper { return improved; } + storm::storage::SparseMatrix submatrix; + storm::storage::SparseMatrix fullSubmatrix; + std::vector stateToFinalEc; + boost::optional::EndComponentEliminatorReturnType> ecResult; + std::vector initialComponentExitToOriginalRow; + private: std::vector createScaledVector(ValueType const& w1, std::vector const& v1, ValueType const& w2, std::vector const& v2) const { @@ -525,7 +781,6 @@ class WeightedReachabilityHelper { return result; } - storm::storage::SparseMatrix submatrix; storm::storage::BitVector rowsWithSum1; std::vector targetRowValues; std::vector conditionRowValues; @@ -534,9 +789,9 @@ class WeightedReachabilityHelper { enum class BisectionMethodBounds { Simple, Advanced }; template -SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds boundOption, uint64_t const initialState, +typename internal::ResultReturnType computeViaBisection(Environment const& env, BisectionMethodBounds boundOption, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, - NormalFormData const& normalForm) { + storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper STORM_LOG_WARN_COND(!env.solver().isForceSoundness(), "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); @@ -556,17 +811,21 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b SolutionType pMax{storm::utility::one()}; if (boundOption == BisectionMethodBounds::Advanced) { - pMin = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); - pMax = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); + auto pMinRes = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); + auto pMaxRes = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); + pMin = pMinRes.initialStateValue; + pMax = pMaxRes.initialStateValue; STORM_LOG_TRACE("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) << ",\n\t Upper bound: " << storm::utility::convertNumber(pMax)); } storm::utility::Extremum lowerBound = storm::utility::zero(); storm::utility::Extremum upperBound = storm::utility::one(); SolutionType middle = (*lowerBound + *upperBound) / 2; + SolverResult res(0); for (uint64_t iterationCount = 1; true; ++iterationCount) { // evaluate the current middle - SolutionType const middleValue = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + res = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + SolutionType const middleValue = res.initialStateValue; // update the bounds and new middle value according to the bisection method if (boundOption == BisectionMethodBounds::Simple) { if (middleValue >= storm::utility::zero()) { @@ -639,7 +898,67 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b } } } - return (*lowerBound + *upperBound) / 2; + + storm::storage::BitVector maybeStatesWithChoice(normalForm.maybeStates.size(), false); + std::unique_ptr> scheduler; + scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + if (res.hasScheduler()) { + uint64_t state = 0; + for (auto& choice : *res.scheduler) { + uint64_t originalChoice; + uint64_t originalState; + + if (state == 0) { + originalChoice = wrh.initialComponentExitToOriginalRow[choice]; + + auto const rowGroups = transitionMatrix.getRowGroupIndices(); + for (originalState = 0; originalState < transitionMatrix.getRowGroupCount(); ++originalState) { + auto const firstRowStateIndex = rowGroups[originalState+1]; + if (firstRowStateIndex > originalChoice) { + originalChoice = originalChoice - rowGroups[originalState]; + break; + } + } + + scheduler->setChoice(originalChoice, originalState); + maybeStatesWithChoice.set(originalState, true); + ++state; + continue; + } + + uint64_t firstRowIndex = wrh.submatrix.getRowGroupIndices()[state]; + originalChoice = firstRowIndex + choice; + if (wrh.ecResult.has_value()) { + originalChoice = wrh.ecResult->newToOldRowMapping[originalChoice]; + } + + auto const rowGroups = wrh.fullSubmatrix.getRowGroupIndices(); + for (originalState = 0; originalState < wrh.fullSubmatrix.getRowGroupCount(); ++originalState) { + auto const firstRowStateIndex = rowGroups[originalState+1]; + if (firstRowStateIndex > originalChoice) { + originalChoice = originalChoice - rowGroups[originalState]; + break; + } + } + + uint64_t index = 0; + for (uint64_t s = 0; s < originalState; ++s) { + index = normalForm.maybeStates.getNextSetIndex(index+1); + } + + originalState = index; + scheduler->setChoice(originalChoice, originalState); + maybeStatesWithChoice.set(originalState, true); + ++state; + } + } + + auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, wrh.stateToFinalEc); + + auto finalResult = ResultReturnType((*lowerBound + *upperBound) / 2, std::move(scheduler)); + + return finalResult; } template @@ -703,6 +1022,7 @@ std::optional handleTrivialCases(uint64_t const initialState, Norm template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::modelchecker::CheckTask const& checkTask, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { @@ -728,14 +1048,16 @@ std::unique_ptr computeConditionalProbabilities(Environment const& << transitionMatrix.getEntryCount() << " transitions."); // storm::utility::Stopwatch sw(true); auto normalFormData = internal::obtainNormalForm(normalFormConstructionEnv, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), - targetStates, conditionStates); + targetStates, conditionStates, checkTask); // sw.stop(); // STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); // Then, we solve the induced problem using the selected algorithm auto const initialState = *goal.relevantValues().begin(); ValueType initialStateValue = -storm::utility::one(); + std::unique_ptr> scheduler = nullptr; if (auto trivialValue = internal::handleTrivialCases(initialState, normalFormData); trivialValue.has_value()) { initialStateValue = *trivialValue; + scheduler = std::unique_ptr>( new storm::storage::Scheduler(transitionMatrix.getRowGroupCount()) ); STORM_LOG_DEBUG("Initial state has trivial value " << initialStateValue); } else { STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState), "Initial state must be a maybe state if it is not a terminal state"); @@ -746,36 +1068,123 @@ std::unique_ptr computeConditionalProbabilities(Environment const& STORM_LOG_INFO("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg << "."); // sw.restart(); switch (alg) { - case ConditionalAlgorithmSetting::Restart: - initialStateValue = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); + case ConditionalAlgorithmSetting::Restart: { + auto result = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, backwardTransitions, normalFormData); + initialStateValue = result.initialStateValue; + scheduler = std::move(result.scheduler); break; - case ConditionalAlgorithmSetting::Bisection: - initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal.direction(), - transitionMatrix, normalFormData); + } + case ConditionalAlgorithmSetting::Bisection: { + auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal.direction(), + transitionMatrix, backwardTransitions, normalFormData); + initialStateValue = result.initialStateValue; + scheduler = std::move(result.scheduler); break; - case ConditionalAlgorithmSetting::BisectionAdvanced: - initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal.direction(), - transitionMatrix, normalFormData); + } + case ConditionalAlgorithmSetting::BisectionAdvanced: { + auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal.direction(), + transitionMatrix, backwardTransitions, normalFormData); + initialStateValue = result.initialStateValue; + scheduler = std::move(result.scheduler); break; - case ConditionalAlgorithmSetting::PolicyIteration: + } + case ConditionalAlgorithmSetting::PolicyIteration: { initialStateValue = internal::computeViaPolicyIteration(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); break; - default: + } + default: { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " << alg); + } } // sw.stop(); // STORM_PRINT_AND_LOG("Time for analyzing the normal form: " << sw << ".\n"); } - return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); + std::unique_ptr result(new ExplicitQuantitativeCheckResult(initialState, initialStateValue)); + + // if produce schedulers was set, we have to construct a scheduler with memory + if (checkTask.isProduceSchedulersSet() && scheduler) { + // not sure about this + storm::utility::graph::computeSchedulerProb1E(normalFormData.targetStates, transitionMatrix, backwardTransitions, normalFormData.targetStates, targetStates, *scheduler); + storm::utility::graph::computeSchedulerProb1E(normalFormData.conditionStates, transitionMatrix, backwardTransitions, normalFormData.conditionStates, conditionStates, *scheduler); + // fill in the scheduler with default choices for states that are missing a choice, these states should be just the ones from which the condition is unreachable + // this is also used to fill choices for the trivial cases + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + if (!scheduler->isChoiceSelected(state)) { + // select an arbitrary choice + scheduler->setChoice(0, state); + } + } + + // create scheduler with memory structure + storm::storage::MemoryStructure::TransitionMatrix memoryTransitions(3, std::vector>(3, boost::none)); + storm::models::sparse::StateLabeling memoryStateLabeling(3); + memoryStateLabeling.addLabel("init_memory"); + memoryStateLabeling.addLabel("condition_reached"); + memoryStateLabeling.addLabel("target_reached"); + memoryStateLabeling.addLabelToState("init_memory", 0); + memoryStateLabeling.addLabelToState("condition_reached", 1); + memoryStateLabeling.addLabelToState("target_reached", 2); + + storm::storage::BitVector allTransitions(transitionMatrix.getEntryCount(), true); + storm::storage::BitVector conditionExitTransitions(transitionMatrix.getEntryCount(), false); + storm::storage::BitVector targetExitTransitions(transitionMatrix.getEntryCount(), false); + + for (auto state : conditionStates) { + for (auto choice : transitionMatrix.getRowGroupIndices(state)) { + for (auto entryIt = transitionMatrix.getRow(choice).begin(); entryIt < transitionMatrix.getRow(choice).end(); ++entryIt) { + conditionExitTransitions.set(entryIt - transitionMatrix.begin(), true); + } + } + } + for (auto state : targetStates) { + for (auto choice : transitionMatrix.getRowGroupIndices(state)) { + for (auto entryIt = transitionMatrix.getRow(choice).begin(); entryIt < transitionMatrix.getRow(choice).end(); ++entryIt) { + targetExitTransitions.set(entryIt - transitionMatrix.begin(), true); + } + } + } + + memoryTransitions[0][0] = allTransitions & ~conditionExitTransitions & ~targetExitTransitions; // if neither condition nor target reached, stay in init_memory + memoryTransitions[0][1] = conditionExitTransitions; + memoryTransitions[0][2] = targetExitTransitions & ~conditionExitTransitions; + memoryTransitions[1][1] = allTransitions; // once condition reached, stay in that memory state + memoryTransitions[2][2] = allTransitions; // once target reached, stay in that memory state + + // this assumes there is a single initial state + auto memoryStructure = storm::storage::MemoryStructure(memoryTransitions, memoryStateLabeling, std::vector(1, 0), true); + + auto finalScheduler = std::unique_ptr>( new storm::storage::Scheduler(transitionMatrix.getRowGroupCount(), std::move(memoryStructure)) ); + + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + // set choices for memory 0 + if (conditionStates.get(state)) { + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates[state], state, 0); + } else if (targetStates.get(state)) { + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates[state], state, 0); + } else { + finalScheduler->setChoice(scheduler->getChoice(state), state, 0); + } + + // set choices for memory 1, these are the choices after condition was reached + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates[state], state, 1); + // set choices for memory 2, these are the choices after target was reached + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates[state], state, 2); + } + + result->asExplicitQuantitativeCheckResult().setScheduler(std::move(finalScheduler)); + } + return result; } template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::modelchecker::CheckTask const& checkTask, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates); template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::modelchecker::CheckTask const& checkTask, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.h b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h index 12e8c0791e..6303a6bd44 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.h +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h @@ -2,6 +2,8 @@ #include #include "storm/solver/SolveGoal.h" +#include "storm/logic/ConditionalFormula.h" +#include "storm/modelchecker/CheckTask.h" namespace storm { class Environment; @@ -22,6 +24,7 @@ class BackwardTransitionCache; template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, + storm::modelchecker::CheckTask const& checkTask, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates); diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index e532228189..5930c02fdd 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -281,7 +281,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com if constexpr (std::is_same_v) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { - return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), + return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); } diff --git a/src/storm/storage/Scheduler.cpp b/src/storm/storage/Scheduler.cpp index 1a42dfe7c1..7e34981310 100644 --- a/src/storm/storage/Scheduler.cpp +++ b/src/storm/storage/Scheduler.cpp @@ -75,6 +75,13 @@ bool Scheduler::isChoiceSelected(BitVector const& selectedStates, uin return true; } +template +bool Scheduler::isChoiceSelected(uint64_t modelState, uint64_t memoryState) const { + STORM_LOG_ASSERT(memoryState < getNumberOfMemoryStates(), "Illegal memory state index"); + STORM_LOG_ASSERT(modelState < schedulerChoices[memoryState].size(), "Illegal model state index"); + return schedulerChoices[memoryState][modelState].isDefined(); +} + template void Scheduler::clearChoice(uint_fast64_t modelState, uint_fast64_t memoryState) { STORM_LOG_ASSERT(memoryState < getNumberOfMemoryStates(), "Illegal memory state index"); @@ -171,6 +178,19 @@ boost::optional const& Scheduler::ge return memoryStructure; } +template +Scheduler Scheduler::getMemorylessSchedulerForMemoryState(uint64_t memoryState) const { + STORM_LOG_ASSERT(memoryState < getNumberOfMemoryStates(), "Illegal memory state index"); + + Scheduler memorylessScheduler(getNumberOfModelStates()); + for (uint64_t modelState = 0; modelState < getNumberOfModelStates(); ++modelState) { + if (schedulerChoices[memoryState][modelState].isDefined()) { + memorylessScheduler.setChoice(schedulerChoices[memoryState][modelState], modelState); + } + } + return memorylessScheduler; +} + template void Scheduler::printToStream(std::ostream& out, std::shared_ptr> model, bool skipUniqueChoices, bool skipDontCareStates) const { diff --git a/src/storm/storage/Scheduler.h b/src/storm/storage/Scheduler.h index 4bf67f486a..e1875212d5 100644 --- a/src/storm/storage/Scheduler.h +++ b/src/storm/storage/Scheduler.h @@ -40,6 +40,11 @@ class Scheduler { */ bool isChoiceSelected(BitVector const& selectedStates, uint64_t memoryState = 0) const; + /*! + * Is the scheduler defined on the given state + */ + bool isChoiceSelected(uint64_t modelState, uint64_t memoryState = 0) const; + /*! * Clears the choice defined by the scheduler for the given state. * @@ -114,6 +119,13 @@ class Scheduler { */ boost::optional const& getMemoryStructure() const; + /*! + * Retrieves a memoryless scheduler that corresponds to the given memory state. + * + * @param memoryState the memory state to fix + */ + Scheduler getMemorylessSchedulerForMemoryState(uint64_t memoryState = 0) const; + /*! * Returns a copy of this scheduler with the new value type */ From e29564a48f433a3f41e68de83edbcaa00dc084b3 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 10 Nov 2025 13:52:18 +0100 Subject: [PATCH 050/102] make risk default in tover --- src/storm-pomdp/generator/GenerateMonitorVerifier.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.h b/src/storm-pomdp/generator/GenerateMonitorVerifier.h index 31c06a654f..cf925d33e6 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.h +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.h @@ -32,7 +32,8 @@ class GenerateMonitorVerifier { std::string acceptingLabel = "accepting"; std::string stepPrefix = "step"; std::string horizonLabel = "horizon"; - bool useRisk = false; + bool useRejectionSampling = true; + bool useRisk = true; }; GenerateMonitorVerifier(storm::models::sparse::Dtmc const& mc, storm::models::sparse::Mdp const& monitor, std::shared_ptr& exprManager, Options const& options); From aac75b33c2a06e975722a422a40144efa0a7a939 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 10 Nov 2025 15:13:00 +0100 Subject: [PATCH 051/102] fix rejection state tover --- .../generator/GenerateMonitorVerifier.cpp | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index b3bc617c20..28dd98e5b2 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -95,7 +95,22 @@ std::shared_ptr> GenerateMonitorVerifier:: observations.push_back(nextObservation++); std::map prodToIndexMap; - std::vector prodInitial; + std::vector rejectToStates; + + state_type rejectionIndex; + if (!options.useRejectionSampling) { + // Add sink state where all invalid transitions go + rejectionIndex = nextStateId++; + builder.newRowGroup(currentRow); + rowActionObservationMap[std::make_pair("end", nextObservation)].grow(currentRow + 1); + rowActionObservationMap[std::make_pair("end", nextObservation)].set(currentRow); + observationUsedActions.push_back({"end"}); + builder.addDiagonalEntry(currentRow++, utility::one()); + observations.push_back(nextObservation++); + rejectToStates.push_back(rejectionIndex); + } + + std::vector initialStates; std::deque todo; for (state_type mc_s_0 : mc.getInitialStates()) { @@ -103,7 +118,9 @@ std::shared_ptr> GenerateMonitorVerifier:: product_state_type prod_s(mc_s_0, mon_s_0); state_type index = nextStateId++; prodToIndexMap[prod_s] = index; - prodInitial.push_back(index); + initialStates.push_back(index); + if (options.useRejectionSampling) + rejectToStates.push_back(index); todo.push_back(prod_s); } } @@ -132,8 +149,8 @@ std::shared_ptr> GenerateMonitorVerifier:: builder.newRowGroup(currentRow); if (monitor.getStateLabeling().getLabelsOfState(mon_from).contains(options.horizonLabel)) { const auto& action = *actions.begin(); - for (state_type initState : prodInitial) { - builder.addNextValue(currentRow, initState, storm::utility::one() / prodInitial.size()); + for (state_type initState : rejectToStates) { + builder.addNextValue(currentRow, initState, storm::utility::one() / rejectToStates.size()); } rowActionObservationMap[std::make_pair(action, currentObservation)].grow(currentRow + 1); rowActionObservationMap[std::make_pair(action, currentObservation)].set(currentRow); @@ -168,11 +185,11 @@ std::shared_ptr> GenerateMonitorVerifier:: // Direct probability not used towards the initial states if (totalProbability < storm::utility::one()) { - for (state_type initState : prodInitial) { + for (state_type initState : rejectToStates) { if (newRow.contains(initState)) - newRow[initState] = newRow[initState] + (1 - totalProbability) / prodInitial.size(); + newRow[initState] = newRow[initState] + (1 - totalProbability) / rejectToStates.size(); else - newRow[initState] = (1 - totalProbability) / prodInitial.size(); + newRow[initState] = (1 - totalProbability) / rejectToStates.size(); } } @@ -211,8 +228,8 @@ std::shared_ptr> GenerateMonitorVerifier:: } for (const auto& action : actionsNotTaken) { - for (state_type initState : prodInitial) { - builder.addNextValue(currentRow, initState, storm::utility::one() / prodInitial.size()); + for (state_type initState : rejectToStates) { + builder.addNextValue(currentRow, initState, storm::utility::one() / rejectToStates.size()); } auto& rowBitVec = rowActionObservationMap[std::make_pair(action, currentObservation)]; rowBitVec.grow(currentRow + 1); @@ -271,7 +288,7 @@ std::shared_ptr> GenerateMonitorVerifier:: } currentObservation++; } - std::cout << "Kept " << rowsToKeep.getNumberOfSetBits() << " out of " << numberOfRows << " rows." << std::endl; + // std::cout << "Kept " << rowsToKeep.getNumberOfSetBits() << " out of " << numberOfRows << " rows." << std::endl; // rowsToKeep.setMultiple(0, numberOfRows); numberOfRows = rowsToKeep.getNumberOfSetBits(); storm::storage::SparseMatrix reducedTransitionMatrix = transMatrix.restrictRows(rowsToKeep); @@ -279,7 +296,7 @@ std::shared_ptr> GenerateMonitorVerifier:: // Create state labeling const state_type numberOfStates = nextStateId; storm::models::sparse::StateLabeling stateLabeling(numberOfStates); - stateLabeling.addLabel("init", storm::storage::BitVector(numberOfStates, prodInitial.begin(), prodInitial.end())); + stateLabeling.addLabel("init", storm::storage::BitVector(numberOfStates, initialStates.begin(), initialStates.end())); stateLabeling.addLabel("goal", storm::storage::BitVector(numberOfStates)); stateLabeling.addLabelToState("goal", goalIndex); @@ -287,6 +304,11 @@ std::shared_ptr> GenerateMonitorVerifier:: stateLabeling.addLabel("stop", storm::storage::BitVector(numberOfStates)); stateLabeling.addLabelToState("stop", stopIndex); + if (!options.useRejectionSampling) { + stateLabeling.addLabel("sink", storm::storage::BitVector(numberOfStates)); + stateLabeling.addLabelToState("sink", rejectionIndex); + } + storm::storage::sparse::ModelComponents components(reducedTransitionMatrix, std::move(stateLabeling)); components.observabilityClasses = std::move(observations); From 247a3bd2f23fcc2da876f8bdf80824bdd5a5ab9d Mon Sep 17 00:00:00 2001 From: Filip Macak Date: Fri, 14 Nov 2025 11:38:14 +0100 Subject: [PATCH 052/102] cleaning up unused code --- .../helper/conditional/ConditionalHelper.cpp | 175 ++++++++++++++---- .../IterativeMinMaxLinearEquationSolver.cpp | 4 +- 2 files changed, 136 insertions(+), 43 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 6df56a96b8..7a7fc61719 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -251,8 +251,7 @@ template NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& relevantStates, - storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, - storm::modelchecker::CheckTask const& checkTask) { + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { storm::storage::BitVector const allStates(transitionMatrix.getRowGroupCount(), true); auto extendedConditionStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); @@ -265,37 +264,19 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver std::vector schedulerChoicesForReachingTargetStates; std::vector schedulerChoicesForReachingConditionStates; - if (!checkTask.isProduceSchedulersSet()) { - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); - } else { - // if produce scheduler is set, we need to store the choices scheduler makes after reaching the condition or target state - if (checkTask.hasReachTargetStatesResult()) { - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates, - std::get<0>(checkTask.getReachTargetStatesResult())); - schedulerChoicesForReachingTargetStates = std::get<1>(checkTask.getReachTargetStatesResult()); - } else { - auto scheduler = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); - schedulerChoicesForReachingTargetStates = std::vector(transitionMatrix.getRowGroupCount(), 0); - if (scheduler) { - for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { - schedulerChoicesForReachingTargetStates[state] = scheduler->getChoice(state).getDeterministicChoice(); - } - } + auto schedulerForTargetStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); + schedulerChoicesForReachingTargetStates = std::vector(transitionMatrix.getRowGroupCount(), 0); + if (schedulerForTargetStates) { + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + schedulerChoicesForReachingTargetStates[state] = schedulerForTargetStates->getChoice(state).getDeterministicChoice(); } + } - if (checkTask.hasReachConditionalStatesResult()) { - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates, - std::get<0>(checkTask.getReachConditionalStatesResult())); - schedulerChoicesForReachingConditionStates = std::get<1>(checkTask.getReachConditionalStatesResult()); - } else { - auto scheduler = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); - schedulerChoicesForReachingConditionStates = std::vector(transitionMatrix.getRowGroupCount(), 0); - if (scheduler) { - for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { - schedulerChoicesForReachingConditionStates[state] = scheduler->getChoice(state).getDeterministicChoice(); - } - } + auto schedulerForConditionStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + schedulerChoicesForReachingConditionStates = std::vector(transitionMatrix.getRowGroupCount(), 0); + if (schedulerForConditionStates) { + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + schedulerChoicesForReachingConditionStates[state] = schedulerForConditionStates->getChoice(state).getDeterministicChoice(); } } @@ -341,13 +322,22 @@ template void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& scheduler, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, storm::storage::BitVector const& maybeStatesWithoutChoice, storm::storage::BitVector const& maybeStatesWithChoice, - std::vector const& stateToFinalEc) { + std::vector const& stateToFinalEc, NormalFormData const& normalForm, + uint64_t initialComponentIndex, storm::storage::BitVector const& initialComponentExitRows, uint64_t chosenInitialComponentExitState, uint64_t chosenInitialComponentExit) { // Compute the EC stay choices for the states in maybeStatesWithChoice storm::storage::BitVector ecStayChoices(transitionMatrix.getRowCount(), false); + storm::storage::BitVector initialComponentStates(transitionMatrix.getRowGroupCount(), false); + // compute initial component states and all choices that stay within a given EC for (auto state : maybeStates) { auto ecIndex = stateToFinalEc[state]; + if (ecIndex == initialComponentIndex) { + initialComponentStates.set(state, true); + continue; // state part of the initial component + } else if (ecIndex == std::numeric_limits::max()) { + continue; + } for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { bool isEcStayChoice = true; for (auto const& entry : transitionMatrix.getRow(choiceIndex)) { @@ -363,8 +353,69 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc } } - storm::utility::graph::computeSchedulerProb1E(maybeStates, transitionMatrix, backwardTransitions, maybeStatesWithoutChoice, maybeStatesWithChoice, + // fill choices for ECs that reach the chosen EC exit + auto const maybeNonICStatesWithoutChoice = maybeStatesWithoutChoice & ~initialComponentStates; + storm::utility::graph::computeSchedulerProb1E(maybeNonICStatesWithoutChoice, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithChoice, scheduler, ecStayChoices); + + // collect all choices from the initial component states and the choices that were selected by the scheduler so far + auto const condOrTargetStates = normalForm.conditionStates | normalForm.targetStates; + auto const rowGroups = transitionMatrix.getRowGroupIndices(); + storm::storage::BitVector allowedChoices(transitionMatrix.getRowCount(), false); + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + if (scheduler.isChoiceSelected(state)) { + auto choiceIndex = scheduler.getChoice(state).getDeterministicChoice(); + allowedChoices.set(rowGroups[state] + choiceIndex, true); + } else if (initialComponentStates.get(state) || condOrTargetStates.get(state)) { + for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { + allowedChoices.set(choiceIndex, true); + } + } + } + + auto const transposedMatrixWithGroups = transitionMatrix.transpose(false); + + // dfs to find which choices in initial component states lead to condOrTargetStates + storm::storage::BitVector choicesThatCanVisitCondOrTargetStates(transitionMatrix.getRowCount(), false); + std::stack toProcess; + for (auto state : condOrTargetStates) { + toProcess.push(state); + } + storm::storage::BitVector visitedStates(transitionMatrix.getRowGroupCount(), false); + visitedStates = condOrTargetStates; + while (!toProcess.empty()) + { + auto currentState = toProcess.top(); + toProcess.pop(); + for (auto const& entry : transposedMatrixWithGroups.getRow(currentState)) { + auto predecessorChoiceIndex = entry.getColumn(); + if (!allowedChoices.get(predecessorChoiceIndex) || choicesThatCanVisitCondOrTargetStates.get(predecessorChoiceIndex)) { + continue; + } + choicesThatCanVisitCondOrTargetStates.set(predecessorChoiceIndex, true); + uint64_t predecessorState = 0; + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + if (predecessorChoiceIndex < rowGroups[state+1]){ + predecessorState = state; + break; + } + } + if (!visitedStates.get(predecessorState)) { + visitedStates.set(predecessorState, true); + toProcess.push(predecessorState); + } + } + } + + // we want to disallow taking initial component exits that can lead to a condition or target state, beside the one exit that was chosen + storm::storage::BitVector disallowedInitialComponentExits = initialComponentExitRows & choicesThatCanVisitCondOrTargetStates; + disallowedInitialComponentExits.set(chosenInitialComponentExit, false); + + storm::storage::BitVector choicesAllowedForInitialComponent = allowedChoices & ~disallowedInitialComponentExits; + storm::storage::BitVector exitStateBitvector(transitionMatrix.getRowGroupCount(), false); + exitStateBitvector.set(chosenInitialComponentExitState, true); + + storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, initialComponentStates, exitStateBitvector, scheduler, choicesAllowedForInitialComponent); } template @@ -467,9 +518,42 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme // Finally, solve the equation system auto result = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); + storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); + for (auto rowIndex : matrix.getRowGroupIndices(initStateInMatrix)) { + uint64_t originalRowIndex = rowIndex; + if (ecElimResult2.has_value()) { + originalRowIndex = ecElimResult2->newToOldRowMapping[originalRowIndex]; + } + if (ecElimResult1.has_value()) { + originalRowIndex = ecElimResult1->newToOldRowMapping[originalRowIndex]; + } + + uint64_t originalState; + uint64_t originalChoice; + auto const rowGroups = maybeMatrix.getRowGroupIndices(); + for (originalState = 0; originalState < maybeMatrix.getRowGroupCount(); ++originalState) { + auto const firstRowStateIndex = rowGroups[originalState+1]; + if (firstRowStateIndex > originalRowIndex) { + originalChoice = originalRowIndex - rowGroups[originalState]; + break; + } + } + + uint64_t index = maybeStates.getNextSetIndex(0); + for (uint64_t s = 0; s < originalState; ++s) { + index = maybeStates.getNextSetIndex(index+1); + } + + originalState = index; + + initialComponentExitRows.set(transitionMatrix.getRowGroupIndices()[originalState]+originalChoice, true); + } + // std::vector finalSchedulerChoices(transitionMatrix.getRowGroupCount(), -1); storm::storage::BitVector maybeStatesWithChoice(maybeStates.size(), false); std::unique_ptr> scheduler; + uint64_t chosenInitialComponentExitState; + uint64_t chosenInitialComponentExit; scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); // std::vector ecsToExits(matrix.getRowGroupCount(), 0); if (result.hasScheduler()) { @@ -494,7 +578,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme } } - uint64_t index = 0; + uint64_t index = maybeStates.getNextSetIndex(0); for (uint64_t s = 0; s < originalState; ++s) { index = maybeStates.getNextSetIndex(index+1); } @@ -504,11 +588,15 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme scheduler->setChoice(originalChoice, originalState); maybeStatesWithChoice.set(originalState, true); // ecsToExits[state] = originalState; + if (state == initStateInMatrix) { + chosenInitialComponentExitState = originalState; + chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState]+originalChoice; + } ++state; } } - std::vector stateToFinalEc(transitionMatrix.getRowGroupCount(), -1); + std::vector stateToFinalEc(transitionMatrix.getRowGroupCount(), std::numeric_limits::max()); uint64_t state = 0; for (auto s : maybeStates) { auto mappedState = state; @@ -519,7 +607,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme } auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, stateToFinalEc); + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); auto finalResult = ResultReturnType(result.initialStateValue, std::move(scheduler)); @@ -546,7 +634,7 @@ class WeightedReachabilityHelper { // An optimal scheduler can intuitively pick the best exiting action of C and enforce that all paths that satisfy the condition exit C through that // action. By eliminating the initial component, we ensure that only policies that actually exit C are considered. The remaining policies have // probability zero of satisfying the condition. - storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); + initialComponentExitRows = storm::storage::BitVector(transitionMatrix.getRowCount(), false); subMatrixRowGroups.set(initialState, false); // temporarily unset initial state std::vector dfsStack = {initialState}; while (!dfsStack.empty()) { @@ -768,6 +856,7 @@ class WeightedReachabilityHelper { std::vector stateToFinalEc; boost::optional::EndComponentEliminatorReturnType> ecResult; std::vector initialComponentExitToOriginalRow; + storm::storage::BitVector initialComponentExitRows; private: std::vector createScaledVector(ValueType const& w1, std::vector const& v1, ValueType const& w2, @@ -901,6 +990,8 @@ typename internal::ResultReturnType computeViaBisection(Environment c storm::storage::BitVector maybeStatesWithChoice(normalForm.maybeStates.size(), false); std::unique_ptr> scheduler; + uint64_t chosenInitialComponentExitState; + uint64_t chosenInitialComponentExit; scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); if (res.hasScheduler()) { uint64_t state = 0; @@ -908,7 +999,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c uint64_t originalChoice; uint64_t originalState; - if (state == 0) { + if (state == wrh.getInternalInitialState()) { originalChoice = wrh.initialComponentExitToOriginalRow[choice]; auto const rowGroups = transitionMatrix.getRowGroupIndices(); @@ -922,6 +1013,8 @@ typename internal::ResultReturnType computeViaBisection(Environment c scheduler->setChoice(originalChoice, originalState); maybeStatesWithChoice.set(originalState, true); + chosenInitialComponentExitState = originalState; + chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState]+originalChoice; ++state; continue; } @@ -941,7 +1034,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c } } - uint64_t index = 0; + uint64_t index = normalForm.maybeStates.getNextSetIndex(0); for (uint64_t s = 0; s < originalState; ++s) { index = normalForm.maybeStates.getNextSetIndex(index+1); } @@ -954,7 +1047,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c } auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, wrh.stateToFinalEc); + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); auto finalResult = ResultReturnType((*lowerBound + *upperBound) / 2, std::move(scheduler)); @@ -1048,7 +1141,7 @@ std::unique_ptr computeConditionalProbabilities(Environment const& << transitionMatrix.getEntryCount() << " transitions."); // storm::utility::Stopwatch sw(true); auto normalFormData = internal::obtainNormalForm(normalFormConstructionEnv, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), - targetStates, conditionStates, checkTask); + targetStates, conditionStates); // sw.stop(); // STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); // Then, we solve the induced problem using the selected algorithm diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp index f64d495009..4dd35b55b2 100644 --- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp @@ -188,8 +188,8 @@ void IterativeMinMaxLinearEquationSolver::extractSchedu } // Set the correct choices. - STORM_LOG_WARN_COND(!viOperatorTriv && !viOperatorNontriv, - "Expected VI operator to be initialized for scheduler extraction. Initializing now, but this is inefficient."); + // STORM_LOG_WARN_COND(!viOperatorTriv && !viOperatorNontriv, + // "Expected VI operator to be initialized for scheduler extraction. Initializing now, but this is inefficient."); if (!viOperatorTriv && !viOperatorNontriv) { setUpViOperator(); } From c55c6a40d3e511e9ea005272eab653be60a9f2ec Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 17 Nov 2025 13:01:52 +0100 Subject: [PATCH 053/102] Change trace message bisection --- .../helper/conditional/ConditionalHelper.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 7a7fc61719..3a98e1b92a 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -948,11 +948,9 @@ typename internal::ResultReturnType computeViaBisection(Environment c } // check for convergence SolutionType const boundDiff = *upperBound - *lowerBound; - STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << storm::utility::convertNumber(*lowerBound) - << ",\n\t Upper bound: " << storm::utility::convertNumber(*upperBound) - << ",\n\t Difference: " << storm::utility::convertNumber(boundDiff) - << ",\n\t Middle val: " << storm::utility::convertNumber(middleValue) << ",\n\t Difference bound: " - << storm::utility::convertNumber((relative ? (precision * *lowerBound) : precision)) << "."); + STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << *lowerBound << ",\n\t Upper bound: " << *upperBound + << ",\n\t Difference: " << boundDiff << ",\n\t Middle val: " << middleValue + << ",\n\t Difference bound: " << (relative ? (precision * *lowerBound) : precision) << "."); if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " << std::setprecision(std::numeric_limits::digits10) @@ -966,6 +964,8 @@ typename internal::ResultReturnType computeViaBisection(Environment c break; } // process the middle value for the next iteration + // This sets the middle value to a rational number with the smallest enumerator/denominator that is still within the bounds + // With close bounds this can lead to the middle being set to exactly the lower or upper bound, thus allowing for an exact answer. if constexpr (storm::NumberTraits::IsExact) { // find a rational number with a concise representation close to middle and within the bounds auto const exactMiddle = middle; From 349cbbc932461d61b8f361d82389a20f87081999 Mon Sep 17 00:00:00 2001 From: Filip Macak Date: Wed, 19 Nov 2025 09:46:27 +0100 Subject: [PATCH 054/102] fixing the conditional scheduler export --- src/storm/modelchecker/CheckTask.h | 44 ++----------------- .../helper/conditional/ConditionalHelper.cpp | 13 ++++++ 2 files changed, 17 insertions(+), 40 deletions(-) diff --git a/src/storm/modelchecker/CheckTask.h b/src/storm/modelchecker/CheckTask.h index ab7b845684..7dc4b28f86 100644 --- a/src/storm/modelchecker/CheckTask.h +++ b/src/storm/modelchecker/CheckTask.h @@ -11,7 +11,6 @@ #include "storm/logic/PlayerCoalition.h" #include "storm/modelchecker/hints/ModelCheckerHint.h" #include "storm/solver/OptimizationDirection.h" -#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/exceptions/InvalidOperationException.h" @@ -53,7 +52,7 @@ class CheckTask { CheckTask substituteFormula(NewFormulaType const& newFormula) const { CheckTask result(newFormula, this->optimizationDirection, this->playerCoalition, this->rewardModel, this->onlyInitialStatesRelevant, this->bound, this->qualitative, this->produceSchedulers, this->hint, - this->robustUncertainty, this->reachConditionalStatesResult, this->reachTargetStatesResult); + this->robustUncertainty); result.updateOperatorInformation(); return result; } @@ -132,8 +131,7 @@ class CheckTask { CheckTask convertValueType() const { return CheckTask(this->formula, this->optimizationDirection, this->playerCoalition, this->rewardModel, this->onlyInitialStatesRelevant, - this->bound, this->qualitative, this->produceSchedulers, this->hint, this->robustUncertainty, - this->reachConditionalStatesResult, this->reachTargetStatesResult + this->bound, this->qualitative, this->produceSchedulers, this->hint, this->robustUncertainty ); } @@ -317,30 +315,6 @@ class CheckTask { robustUncertainty = robust; } - void setReachConditionalStatesResult(std::tuple, std::vector> const& result) { - reachConditionalStatesResult = result; - } - - bool hasReachConditionalStatesResult() const { - return static_cast(reachConditionalStatesResult); - } - - std::tuple, std::vector> const& getReachConditionalStatesResult() const { - return reachConditionalStatesResult.get(); - } - - void setReachTargetStatesResult(std::tuple, std::vector> const& result) { - reachTargetStatesResult = result; - } - - bool hasReachTargetStatesResult() const { - return static_cast(reachTargetStatesResult); - } - - std::tuple, std::vector> const& getReachTargetStatesResult() const { - return reachTargetStatesResult.get(); - } - private: /*! * Creates a task object with the given options. @@ -360,8 +334,7 @@ class CheckTask { CheckTask(std::reference_wrapper const& formula, boost::optional const& optimizationDirection, boost::optional playerCoalition, boost::optional const& rewardModel, bool onlyInitialStatesRelevant, boost::optional const& bound, bool qualitative, bool produceSchedulers, std::shared_ptr const& hint, - bool robust, boost::optional, std::vector>> const& reachConditionalStatesResult, - boost::optional, std::vector>> const& reachTargetStatesResult) + bool robust) : formula(formula), optimizationDirection(optimizationDirection), playerCoalition(playerCoalition), @@ -371,9 +344,7 @@ class CheckTask { qualitative(qualitative), produceSchedulers(produceSchedulers), hint(hint), - robustUncertainty(robust), - reachConditionalStatesResult(reachConditionalStatesResult), - reachTargetStatesResult(reachTargetStatesResult) { + robustUncertainty(robust) { // Intentionally left empty. } @@ -405,13 +376,6 @@ class CheckTask { // A hint that might contain information that speeds up the modelchecking process (if supported by the model checker) std::shared_ptr hint; - // TODO I'm not sure if these should be templated or not - // If set, the result will be used for conditional states in model checking of conditional properties. - boost::optional, std::vector>> reachConditionalStatesResult; - - // If set, the result will be used for target states in model checking of conditional properties. - boost::optional, std::vector>> reachTargetStatesResult; - /// Whether uncertainty should be resolved robust (standard) or angelically. bool robustUncertainty; }; diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 7a7fc61719..1b3f9632fe 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -416,6 +416,19 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc exitStateBitvector.set(chosenInitialComponentExitState, true); storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, initialComponentStates, exitStateBitvector, scheduler, choicesAllowedForInitialComponent); + + // fill the choices of initial component states that do not have a choice yet + // these states should not reach the condition or target states under the constructed scheduler + for (auto state : initialComponentStates) { + if (!scheduler.isChoiceSelected(state)) { + for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { + if (!choicesThatCanVisitCondOrTargetStates.get(choiceIndex)) { + scheduler.setChoice(choiceIndex - rowGroups[state], state); + break; + } + } + } + } } template From 33e22ce0042f2a15003861e894a2c41d640d45f0 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 19 Nov 2025 10:21:03 +0100 Subject: [PATCH 055/102] add conditional threshold --- .../helper/conditional/ConditionalHelper.cpp | 183 +++++++++++------- 1 file changed, 113 insertions(+), 70 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 3a98e1b92a..b359163038 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -16,7 +16,9 @@ #include "storm/utility/Extremum.h" #include "storm/utility/KwekMehlhorn.h" #include "storm/utility/SignalHandler.h" +#include "storm/utility/constants.h" #include "storm/utility/graph.h" +#include "storm/utility/logging.h" #include "storm/utility/macros.h" #include "storm/modelchecker/prctl/helper/MDPModelCheckingHelperReturnType.h" @@ -29,9 +31,10 @@ namespace storm::modelchecker { namespace internal { template -boost::optional::EndComponentEliminatorReturnType> eliminateEndComponents(storm::storage::BitVector possibleEcStates, bool addRowAtRepresentativeState, std::optional representativeRowEntry, - storm::storage::SparseMatrix& matrix, uint64_t& initialState, storm::storage::BitVector& rowsWithSum1, - std::vector& rowValues1, storm::OptionalRef> rowValues2 = {}) { +boost::optional::EndComponentEliminatorReturnType> eliminateEndComponents( + storm::storage::BitVector possibleEcStates, bool addRowAtRepresentativeState, std::optional representativeRowEntry, + storm::storage::SparseMatrix& matrix, uint64_t& initialState, storm::storage::BitVector& rowsWithSum1, std::vector& rowValues1, + storm::OptionalRef> rowValues2 = {}) { storm::storage::MaximalEndComponentDecomposition ecs(matrix, matrix.transpose(true), possibleEcStates, rowsWithSum1); if (ecs.empty()) { return boost::none; // nothing to do @@ -103,8 +106,8 @@ struct SolverResult { template typename internal::SolverResult solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, - std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, - storm::solver::OptimizationDirection const dir, uint64_t const initialState) { + std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, + storm::solver::OptimizationDirection const dir, uint64_t const initialState) { // Initialize the solution vector. std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); @@ -164,17 +167,17 @@ void computeReachabilityProbabilities(Environment const& env, std::map -std::unique_ptr> computeReachabilityProbabilitiesAndScheduler(Environment const& env, - std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, - storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { +std::unique_ptr> computeReachabilityProbabilitiesAndScheduler( + Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, + storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { if (initialStates.empty()) { // nothing to do return nullptr; } auto result = helper::SparseMdpPrctlHelper::computeUntilProbabilities( - env, storm::solver::SolveGoal(dir, initialStates), transitionMatrix, transitionMatrix.transpose(true), storm::storage::BitVector(targetStates.size(), true), - targetStates, false, true); + env, storm::solver::SolveGoal(dir, initialStates), transitionMatrix, transitionMatrix.transpose(true), + storm::storage::BitVector(targetStates.size(), true), targetStates, false, true); for (auto initState : initialStates) { auto const& val = result.values[initState]; if (!storm::utility::isZero(val)) { @@ -192,7 +195,8 @@ std::unique_ptr> computeReachabilityProbabi template void computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, - storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates, std::vector const& precomputedReachProbs) { + storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates, + std::vector const& precomputedReachProbs) { if (initialStates.empty()) { // nothing to do return; } @@ -230,8 +234,10 @@ struct NormalFormData { // TerminalStates is a superset of conditionStates and dom(nonZeroTargetStateValues). // For a terminalState that is not a conditionState, it is impossible to (reach the condition and not reach the target). - std::vector const schedulerChoicesForReachingTargetStates; // Scheduler choices for reaching target states, used for constructing the resulting scheduler - std::vector const schedulerChoicesForReachingConditionStates; // Scheduler choices for reaching condition states, used for constructing the resulting scheduler + std::vector const + schedulerChoicesForReachingTargetStates; // Scheduler choices for reaching target states, used for constructing the resulting scheduler + std::vector const + schedulerChoicesForReachingConditionStates; // Scheduler choices for reaching condition states, used for constructing the resulting scheduler ValueType getTargetValue(uint64_t state) const { STORM_LOG_ASSERT(terminalStates.get(state), "Tried to get target value for non-terminal state"); @@ -264,7 +270,8 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver std::vector schedulerChoicesForReachingTargetStates; std::vector schedulerChoicesForReachingConditionStates; - auto schedulerForTargetStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); + auto schedulerForTargetStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, + allStates, extendedTargetStates); schedulerChoicesForReachingTargetStates = std::vector(transitionMatrix.getRowGroupCount(), 0); if (schedulerForTargetStates) { for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { @@ -272,7 +279,8 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver } } - auto schedulerForConditionStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + auto schedulerForConditionStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, + targetAndNotCondFailStates, allStates, extendedConditionStates); schedulerChoicesForReachingConditionStates = std::vector(transitionMatrix.getRowGroupCount(), 0); if (schedulerForConditionStates) { for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { @@ -322,9 +330,9 @@ template void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& scheduler, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, storm::storage::BitVector const& maybeStatesWithoutChoice, storm::storage::BitVector const& maybeStatesWithChoice, - std::vector const& stateToFinalEc, NormalFormData const& normalForm, - uint64_t initialComponentIndex, storm::storage::BitVector const& initialComponentExitRows, uint64_t chosenInitialComponentExitState, uint64_t chosenInitialComponentExit) { - + std::vector const& stateToFinalEc, NormalFormData const& normalForm, uint64_t initialComponentIndex, + storm::storage::BitVector const& initialComponentExitRows, uint64_t chosenInitialComponentExitState, + uint64_t chosenInitialComponentExit) { // Compute the EC stay choices for the states in maybeStatesWithChoice storm::storage::BitVector ecStayChoices(transitionMatrix.getRowCount(), false); storm::storage::BitVector initialComponentStates(transitionMatrix.getRowGroupCount(), false); @@ -362,7 +370,8 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc auto const condOrTargetStates = normalForm.conditionStates | normalForm.targetStates; auto const rowGroups = transitionMatrix.getRowGroupIndices(); storm::storage::BitVector allowedChoices(transitionMatrix.getRowCount(), false); - for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + auto const rowGroupCount = transitionMatrix.getRowGroupCount(); + for (uint64_t state = 0; state < rowGroupCount; ++state) { if (scheduler.isChoiceSelected(state)) { auto choiceIndex = scheduler.getChoice(state).getDeterministicChoice(); allowedChoices.set(rowGroups[state] + choiceIndex, true); @@ -381,10 +390,9 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc for (auto state : condOrTargetStates) { toProcess.push(state); } - storm::storage::BitVector visitedStates(transitionMatrix.getRowGroupCount(), false); + storm::storage::BitVector visitedStates(rowGroupCount, false); visitedStates = condOrTargetStates; - while (!toProcess.empty()) - { + while (!toProcess.empty()) { auto currentState = toProcess.top(); toProcess.pop(); for (auto const& entry : transposedMatrixWithGroups.getRow(currentState)) { @@ -394,8 +402,8 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc } choicesThatCanVisitCondOrTargetStates.set(predecessorChoiceIndex, true); uint64_t predecessorState = 0; - for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { - if (predecessorChoiceIndex < rowGroups[state+1]){ + for (uint64_t state = 0; state < rowGroupCount; ++state) { + if (predecessorChoiceIndex < rowGroups[state + 1]) { predecessorState = state; break; } @@ -415,12 +423,14 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc storm::storage::BitVector exitStateBitvector(transitionMatrix.getRowGroupCount(), false); exitStateBitvector.set(chosenInitialComponentExitState, true); - storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, initialComponentStates, exitStateBitvector, scheduler, choicesAllowedForInitialComponent); + storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, initialComponentStates, exitStateBitvector, scheduler, + choicesAllowedForInitialComponent); } template struct ResultReturnType { - ResultReturnType(ValueType initialStateValue, std::unique_ptr>&& scheduler = nullptr) : initialStateValue(initialStateValue), scheduler(std::move(scheduler)) { + ResultReturnType(ValueType initialStateValue, std::unique_ptr>&& scheduler = nullptr) + : initialStateValue(initialStateValue), scheduler(std::move(scheduler)) { // Intentionally left empty. } @@ -437,9 +447,11 @@ struct ResultReturnType { // @see doi.org/10.1007/978-3-642-54862-8_43 */ template -typename internal::ResultReturnType computeViaRestartMethod(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, - NormalFormData const& normalForm) { +typename internal::ResultReturnType computeViaRestartMethod(Environment const& env, uint64_t const initialState, + storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + NormalFormData const& normalForm) { auto const& maybeStates = normalForm.maybeStates; auto const stateToMatrixIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); auto const numMaybeStates = maybeStates.getNumberOfSetBits(); @@ -532,7 +544,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme uint64_t originalChoice; auto const rowGroups = maybeMatrix.getRowGroupIndices(); for (originalState = 0; originalState < maybeMatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState+1]; + auto const firstRowStateIndex = rowGroups[originalState + 1]; if (firstRowStateIndex > originalRowIndex) { originalChoice = originalRowIndex - rowGroups[originalState]; break; @@ -541,12 +553,12 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme uint64_t index = maybeStates.getNextSetIndex(0); for (uint64_t s = 0; s < originalState; ++s) { - index = maybeStates.getNextSetIndex(index+1); + index = maybeStates.getNextSetIndex(index + 1); } originalState = index; - initialComponentExitRows.set(transitionMatrix.getRowGroupIndices()[originalState]+originalChoice, true); + initialComponentExitRows.set(transitionMatrix.getRowGroupIndices()[originalState] + originalChoice, true); } // std::vector finalSchedulerChoices(transitionMatrix.getRowGroupCount(), -1); @@ -571,7 +583,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme uint64_t originalState; auto const rowGroups = maybeMatrix.getRowGroupIndices(); for (originalState = 0; originalState < maybeMatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState+1]; + auto const firstRowStateIndex = rowGroups[originalState + 1]; if (firstRowStateIndex > originalChoice) { originalChoice = originalChoice - rowGroups[originalState]; break; @@ -580,7 +592,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme uint64_t index = maybeStates.getNextSetIndex(0); for (uint64_t s = 0; s < originalState; ++s) { - index = maybeStates.getNextSetIndex(index+1); + index = maybeStates.getNextSetIndex(index + 1); } originalState = index; @@ -590,7 +602,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme // ecsToExits[state] = originalState; if (state == initStateInMatrix) { chosenInitialComponentExitState = originalState; - chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState]+originalChoice; + chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState] + originalChoice; } ++state; } @@ -607,7 +619,9 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme } auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, + stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitRows, chosenInitialComponentExitState, + chosenInitialComponentExit); auto finalResult = ResultReturnType(result.initialStateValue, std::move(scheduler)); @@ -738,12 +752,14 @@ class WeightedReachabilityHelper { // For all remaining ECs, staying in an EC forever is reflected by collecting a value of zero for both, target and condition storm::storage::BitVector allExceptInit(numSubmatrixRowGroups, true); allExceptInit.set(initialStateInSubmatrix, false); - ecResult = eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, conditionRowValues); + ecResult = eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, + conditionRowValues); STORM_LOG_INFO("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " << submatrix.getEntryCount() << " transitions."); // if (ecElimResult.has_value()) { - // ecResult = std::make_unique::EndComponentEliminatorReturnType>(std::move(*ecElimResult)); + // ecResult = std::make_unique::EndComponentEliminatorReturnType>(std::move(*ecElimResult)); // } stateToFinalEc.resize(transitionMatrix.getRowGroupCount(), -1); @@ -760,11 +776,10 @@ class WeightedReachabilityHelper { stateToFinalEc[s] = mappedState; state++; } - } internal::SolverResult computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, - ValueType const& conditionWeight) const { + ValueType const& conditionWeight) const { auto rowValues = createScaledVector(targetWeight, targetRowValues, conditionWeight, conditionRowValues); // Initialize the solution vector. @@ -879,8 +894,10 @@ class WeightedReachabilityHelper { enum class BisectionMethodBounds { Simple, Advanced }; template typename internal::ResultReturnType computeViaBisection(Environment const& env, BisectionMethodBounds boundOption, uint64_t const initialState, - storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { + storm::solver::SolveGoal goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + NormalFormData const& normalForm) { // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper STORM_LOG_WARN_COND(!env.solver().isForceSoundness(), "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); @@ -900,8 +917,10 @@ typename internal::ResultReturnType computeViaBisection(Environment c SolutionType pMax{storm::utility::one()}; if (boundOption == BisectionMethodBounds::Advanced) { - auto pMinRes = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); - auto pMaxRes = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); + auto pMinRes = + wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); + auto pMaxRes = + wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); pMin = pMinRes.initialStateValue; pMax = pMaxRes.initialStateValue; STORM_LOG_TRACE("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) @@ -909,11 +928,16 @@ typename internal::ResultReturnType computeViaBisection(Environment c } storm::utility::Extremum lowerBound = storm::utility::zero(); storm::utility::Extremum upperBound = storm::utility::one(); - SolutionType middle = (*lowerBound + *upperBound) / 2; + SolutionType middle; + if (goal.isBounded()) { + middle = goal.thresholdValue(); + } else { + middle = (*lowerBound + *upperBound) / 2; + } SolverResult res(0); for (uint64_t iterationCount = 1; true; ++iterationCount) { // evaluate the current middle - res = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + res = wrh.computeWeightedDiff(env, goal.direction(), storm::utility::one(), -middle); SolutionType const middleValue = res.initialStateValue; // update the bounds and new middle value according to the bisection method if (boundOption == BisectionMethodBounds::Simple) { @@ -951,12 +975,25 @@ typename internal::ResultReturnType computeViaBisection(Environment c STORM_LOG_TRACE("Iteration #" << iterationCount << ":\n\t Lower bound: " << *lowerBound << ",\n\t Upper bound: " << *upperBound << ",\n\t Difference: " << boundDiff << ",\n\t Middle val: " << middleValue << ",\n\t Difference bound: " << (relative ? (precision * *lowerBound) : precision) << "."); + if (goal.isBounded()) { + STORM_LOG_TRACE("Using threshold " << storm::utility::convertNumber(goal.thresholdValue()) << " with comparison " + << (goal.boundIsALowerBound() ? (goal.boundIsStrict() ? ">" : ">=") : (goal.boundIsStrict() ? "<" : "<=")) + << "."); + } if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " << std::setprecision(std::numeric_limits::digits10) << storm::utility::convertNumber(boundDiff) << "."); break; } + // Check if bounds are fully below or above threshold + if (goal.isBounded() && (*upperBound <= goal.thresholdValue() || (*lowerBound >= goal.thresholdValue()))) { + STORM_LOG_INFO("Bisection method determined result after " << iterationCount << " iterations. Found bounds are [" + << storm::utility::convertNumber(*lowerBound) << ", " + << storm::utility::convertNumber(*upperBound) << "], threshold is " + << storm::utility::convertNumber(goal.thresholdValue()) << "."); + break; + } // check for early termination if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Bisection solver aborted after " << iterationCount << "iterations. Bound difference is " @@ -1004,7 +1041,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c auto const rowGroups = transitionMatrix.getRowGroupIndices(); for (originalState = 0; originalState < transitionMatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState+1]; + auto const firstRowStateIndex = rowGroups[originalState + 1]; if (firstRowStateIndex > originalChoice) { originalChoice = originalChoice - rowGroups[originalState]; break; @@ -1014,7 +1051,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c scheduler->setChoice(originalChoice, originalState); maybeStatesWithChoice.set(originalState, true); chosenInitialComponentExitState = originalState; - chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState]+originalChoice; + chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState] + originalChoice; ++state; continue; } @@ -1027,7 +1064,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c auto const rowGroups = wrh.fullSubmatrix.getRowGroupIndices(); for (originalState = 0; originalState < wrh.fullSubmatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState+1]; + auto const firstRowStateIndex = rowGroups[originalState + 1]; if (firstRowStateIndex > originalChoice) { originalChoice = originalChoice - rowGroups[originalState]; break; @@ -1036,7 +1073,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c uint64_t index = normalForm.maybeStates.getNextSetIndex(0); for (uint64_t s = 0; s < originalState; ++s) { - index = normalForm.maybeStates.getNextSetIndex(index+1); + index = normalForm.maybeStates.getNextSetIndex(index + 1); } originalState = index; @@ -1047,7 +1084,9 @@ typename internal::ResultReturnType computeViaBisection(Environment c } auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, + wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitRows, + chosenInitialComponentExitState, chosenInitialComponentExit); auto finalResult = ResultReturnType((*lowerBound + *upperBound) / 2, std::move(scheduler)); @@ -1150,7 +1189,7 @@ std::unique_ptr computeConditionalProbabilities(Environment const& std::unique_ptr> scheduler = nullptr; if (auto trivialValue = internal::handleTrivialCases(initialState, normalFormData); trivialValue.has_value()) { initialStateValue = *trivialValue; - scheduler = std::unique_ptr>( new storm::storage::Scheduler(transitionMatrix.getRowGroupCount()) ); + scheduler = std::unique_ptr>(new storm::storage::Scheduler(transitionMatrix.getRowGroupCount())); STORM_LOG_DEBUG("Initial state has trivial value " << initialStateValue); } else { STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState), "Initial state must be a maybe state if it is not a terminal state"); @@ -1162,21 +1201,22 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // sw.restart(); switch (alg) { case ConditionalAlgorithmSetting::Restart: { - auto result = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, backwardTransitions, normalFormData); + auto result = + internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, backwardTransitions, normalFormData); initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; } case ConditionalAlgorithmSetting::Bisection: { - auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal.direction(), - transitionMatrix, backwardTransitions, normalFormData); + auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal, transitionMatrix, + backwardTransitions, normalFormData); initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; } case ConditionalAlgorithmSetting::BisectionAdvanced: { - auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal.direction(), - transitionMatrix, backwardTransitions, normalFormData); + auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal, transitionMatrix, + backwardTransitions, normalFormData); initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; @@ -1197,10 +1237,12 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // if produce schedulers was set, we have to construct a scheduler with memory if (checkTask.isProduceSchedulersSet() && scheduler) { // not sure about this - storm::utility::graph::computeSchedulerProb1E(normalFormData.targetStates, transitionMatrix, backwardTransitions, normalFormData.targetStates, targetStates, *scheduler); - storm::utility::graph::computeSchedulerProb1E(normalFormData.conditionStates, transitionMatrix, backwardTransitions, normalFormData.conditionStates, conditionStates, *scheduler); - // fill in the scheduler with default choices for states that are missing a choice, these states should be just the ones from which the condition is unreachable - // this is also used to fill choices for the trivial cases + storm::utility::graph::computeSchedulerProb1E(normalFormData.targetStates, transitionMatrix, backwardTransitions, normalFormData.targetStates, + targetStates, *scheduler); + storm::utility::graph::computeSchedulerProb1E(normalFormData.conditionStates, transitionMatrix, backwardTransitions, normalFormData.conditionStates, + conditionStates, *scheduler); + // fill in the scheduler with default choices for states that are missing a choice, these states should be just the ones from which the condition is + // unreachable this is also used to fill choices for the trivial cases for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { if (!scheduler->isChoiceSelected(state)) { // select an arbitrary choice @@ -1237,7 +1279,8 @@ std::unique_ptr computeConditionalProbabilities(Environment const& } } - memoryTransitions[0][0] = allTransitions & ~conditionExitTransitions & ~targetExitTransitions; // if neither condition nor target reached, stay in init_memory + memoryTransitions[0][0] = + allTransitions & ~conditionExitTransitions & ~targetExitTransitions; // if neither condition nor target reached, stay in init_memory memoryTransitions[0][1] = conditionExitTransitions; memoryTransitions[0][2] = targetExitTransitions & ~conditionExitTransitions; memoryTransitions[1][1] = allTransitions; // once condition reached, stay in that memory state @@ -1246,7 +1289,8 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // this assumes there is a single initial state auto memoryStructure = storm::storage::MemoryStructure(memoryTransitions, memoryStateLabeling, std::vector(1, 0), true); - auto finalScheduler = std::unique_ptr>( new storm::storage::Scheduler(transitionMatrix.getRowGroupCount(), std::move(memoryStructure)) ); + auto finalScheduler = std::unique_ptr>( + new storm::storage::Scheduler(transitionMatrix.getRowGroupCount(), std::move(memoryStructure))); for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { // set choices for memory 0 @@ -1276,11 +1320,10 @@ template std::unique_ptr computeConditionalProbabilities(Environmen storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates); -template std::unique_ptr computeConditionalProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, - storm::modelchecker::CheckTask const& checkTask, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, - storm::storage::BitVector const& targetStates, - storm::storage::BitVector const& conditionStates); +template std::unique_ptr computeConditionalProbabilities( + Environment const& env, storm::solver::SolveGoal&& goal, + storm::modelchecker::CheckTask const& checkTask, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates); } // namespace storm::modelchecker From 523b9f6dc5a87bfb645070c2b4cae1829b9e07eb Mon Sep 17 00:00:00 2001 From: Filip Macak Date: Wed, 19 Nov 2025 18:51:02 +0100 Subject: [PATCH 056/102] fixing the conditional scheduler export --- .../helper/conditional/ConditionalHelper.cpp | 57 +++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 1b3f9632fe..f4752097ea 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -323,7 +323,8 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, storm::storage::BitVector const& maybeStatesWithoutChoice, storm::storage::BitVector const& maybeStatesWithChoice, std::vector const& stateToFinalEc, NormalFormData const& normalForm, - uint64_t initialComponentIndex, storm::storage::BitVector const& initialComponentExitRows, uint64_t chosenInitialComponentExitState, uint64_t chosenInitialComponentExit) { + uint64_t initialComponentIndex, storm::storage::BitVector const& initialComponentExitStates, storm::storage::BitVector const& initialComponentExitRows, + uint64_t chosenInitialComponentExitState, uint64_t chosenInitialComponentExit) { // Compute the EC stay choices for the states in maybeStatesWithChoice storm::storage::BitVector ecStayChoices(transitionMatrix.getRowCount(), false); @@ -410,8 +411,49 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc // we want to disallow taking initial component exits that can lead to a condition or target state, beside the one exit that was chosen storm::storage::BitVector disallowedInitialComponentExits = initialComponentExitRows & choicesThatCanVisitCondOrTargetStates; disallowedInitialComponentExits.set(chosenInitialComponentExit, false); - storm::storage::BitVector choicesAllowedForInitialComponent = allowedChoices & ~disallowedInitialComponentExits; + + storm::storage::BitVector goodInitialComponentStates = initialComponentStates; + storm::storage::BitVector goodInitialComponentStatesFixpoint = initialComponentStates; + for (auto state : initialComponentExitStates) { + bool allChoicesAreDisallowed = true; + for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { + if (!disallowedInitialComponentExits.get(choiceIndex)) { + allChoicesAreDisallowed = false; + break; + } + } + if (allChoicesAreDisallowed) { + goodInitialComponentStates.set(state, false); + } + } + + while (goodInitialComponentStates.getNumberOfSetBits() != goodInitialComponentStatesFixpoint.getNumberOfSetBits()) { + goodInitialComponentStatesFixpoint = goodInitialComponentStates; + for (auto state : goodInitialComponentStates) { + bool allChoicesAreDisallowed = true; + for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { + bool hasBadSuccessor = false; + for (auto const& entry : transitionMatrix.getRow(choiceIndex)) { + auto targetState = entry.getColumn(); + if (!goodInitialComponentStates.get(targetState)) { + hasBadSuccessor = true; + break; + } + } + if (hasBadSuccessor) { + choicesAllowedForInitialComponent.set(choiceIndex, false); + } else { + allChoicesAreDisallowed = false; + } + } + if (allChoicesAreDisallowed) { + goodInitialComponentStates.set(state, false); + } + } + } + + storm::storage::BitVector exitStateBitvector(transitionMatrix.getRowGroupCount(), false); exitStateBitvector.set(chosenInitialComponentExitState, true); @@ -422,7 +464,7 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc for (auto state : initialComponentStates) { if (!scheduler.isChoiceSelected(state)) { for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { - if (!choicesThatCanVisitCondOrTargetStates.get(choiceIndex)) { + if (choicesAllowedForInitialComponent.get(choiceIndex)) { scheduler.setChoice(choiceIndex - rowGroups[state], state); break; } @@ -532,6 +574,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme auto result = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); + storm::storage::BitVector initialComponentExitStates(transitionMatrix.getRowGroupCount(), false); for (auto rowIndex : matrix.getRowGroupIndices(initStateInMatrix)) { uint64_t originalRowIndex = rowIndex; if (ecElimResult2.has_value()) { @@ -560,6 +603,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme originalState = index; initialComponentExitRows.set(transitionMatrix.getRowGroupIndices()[originalState]+originalChoice, true); + initialComponentExitStates.set(originalState, true); } // std::vector finalSchedulerChoices(transitionMatrix.getRowGroupCount(), -1); @@ -620,7 +664,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme } auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitStates, initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); auto finalResult = ResultReturnType(result.initialStateValue, std::move(scheduler)); @@ -648,6 +692,7 @@ class WeightedReachabilityHelper { // action. By eliminating the initial component, we ensure that only policies that actually exit C are considered. The remaining policies have // probability zero of satisfying the condition. initialComponentExitRows = storm::storage::BitVector(transitionMatrix.getRowCount(), false); + initialComponentExitStates = storm::storage::BitVector(transitionMatrix.getRowGroupCount(), false); subMatrixRowGroups.set(initialState, false); // temporarily unset initial state std::vector dfsStack = {initialState}; while (!dfsStack.empty()) { @@ -667,6 +712,7 @@ class WeightedReachabilityHelper { } else { initialComponentExitToOriginalRow.push_back(rowIndex); initialComponentExitRows.set(rowIndex, true); + initialComponentExitStates.set(state, true); } } } @@ -870,6 +916,7 @@ class WeightedReachabilityHelper { boost::optional::EndComponentEliminatorReturnType> ecResult; std::vector initialComponentExitToOriginalRow; storm::storage::BitVector initialComponentExitRows; + storm::storage::BitVector initialComponentExitStates; private: std::vector createScaledVector(ValueType const& w1, std::vector const& v1, ValueType const& w2, @@ -1060,7 +1107,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c } auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitStates, wrh.initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); auto finalResult = ResultReturnType((*lowerBound + *upperBound) / 2, std::move(scheduler)); From d491da46cab0730494d8f71b9801d235524385bf Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 20 Nov 2025 10:57:24 +0100 Subject: [PATCH 057/102] fix bug in bitvector and bisection schedulers --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 2 +- src/storm/storage/BitVector.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index b359163038..ee7e7afa8a 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -666,7 +666,6 @@ class WeightedReachabilityHelper { } } } else { - initialComponentExitToOriginalRow.push_back(rowIndex); initialComponentExitRows.set(rowIndex, true); } } @@ -738,6 +737,7 @@ class WeightedReachabilityHelper { if (state == initialState) { for (auto origRowIndex : initialComponentExitRows) { processRow(origRowIndex); + initialComponentExitToOriginalRow.push_back(origRowIndex); } } else { for (auto origRowIndex : transitionMatrix.getRowGroupIndices(state)) { diff --git a/src/storm/storage/BitVector.cpp b/src/storm/storage/BitVector.cpp index 88e6fb0e2b..d3408e2810 100644 --- a/src/storm/storage/BitVector.cpp +++ b/src/storm/storage/BitVector.cpp @@ -721,6 +721,10 @@ std::vector BitVector::getNumberOfSetBitsBeforeIndices() const { } ++currentNumberOfSetBits; } + while (lastIndex < this->size()) { + bitsSetBeforeIndices.push_back(currentNumberOfSetBits); + ++lastIndex; + } return bitsSetBeforeIndices; } From c1d843b6b0dcb201bd6dd9e6cecadeba52533dd5 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 20 Nov 2025 12:06:08 +0100 Subject: [PATCH 058/102] fix scheduler of bisection conditional --- .../helper/conditional/ConditionalHelper.cpp | 43 ++++++------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 20b1d80b5f..2d43f1557e 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -796,11 +796,12 @@ class WeightedReachabilityHelper { if (state == initialState) { for (auto origRowIndex : initialComponentExitRows) { processRow(origRowIndex); - initialComponentExitToOriginalRow.push_back(origRowIndex); + subMatrixRowToOriginalRow.push_back(origRowIndex); } } else { for (auto origRowIndex : transitionMatrix.getRowGroupIndices(state)) { processRow(origRowIndex); + subMatrixRowToOriginalRow.push_back(origRowIndex); } } } @@ -929,7 +930,7 @@ class WeightedReachabilityHelper { storm::storage::SparseMatrix fullSubmatrix; std::vector stateToFinalEc; boost::optional::EndComponentEliminatorReturnType> ecResult; - std::vector initialComponentExitToOriginalRow; + std::vector subMatrixRowToOriginalRow; storm::storage::BitVector initialComponentExitRows; storm::storage::BitVector initialComponentExitStates; @@ -1096,34 +1097,16 @@ typename internal::ResultReturnType computeViaBisection(Environment c uint64_t originalChoice; uint64_t originalState; - if (state == wrh.getInternalInitialState()) { - originalChoice = wrh.initialComponentExitToOriginalRow[choice]; - - auto const rowGroups = transitionMatrix.getRowGroupIndices(); - for (originalState = 0; originalState < transitionMatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState + 1]; - if (firstRowStateIndex > originalChoice) { - originalChoice = originalChoice - rowGroups[originalState]; - break; - } - } - - scheduler->setChoice(originalChoice, originalState); - maybeStatesWithChoice.set(originalState, true); - chosenInitialComponentExitState = originalState; - chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState] + originalChoice; - ++state; - continue; - } - uint64_t firstRowIndex = wrh.submatrix.getRowGroupIndices()[state]; originalChoice = firstRowIndex + choice; if (wrh.ecResult.has_value()) { originalChoice = wrh.ecResult->newToOldRowMapping[originalChoice]; } - auto const rowGroups = wrh.fullSubmatrix.getRowGroupIndices(); - for (originalState = 0; originalState < wrh.fullSubmatrix.getRowGroupCount(); ++originalState) { + originalChoice = wrh.subMatrixRowToOriginalRow[originalChoice]; + + auto const& rowGroups = transitionMatrix.getRowGroupIndices(); + for (originalState = 0; originalState < transitionMatrix.getRowGroupCount(); ++originalState) { auto const firstRowStateIndex = rowGroups[originalState + 1]; if (firstRowStateIndex > originalChoice) { originalChoice = originalChoice - rowGroups[originalState]; @@ -1131,14 +1114,14 @@ typename internal::ResultReturnType computeViaBisection(Environment c } } - uint64_t index = normalForm.maybeStates.getNextSetIndex(0); - for (uint64_t s = 0; s < originalState; ++s) { - index = normalForm.maybeStates.getNextSetIndex(index + 1); - } - - originalState = index; scheduler->setChoice(originalChoice, originalState); maybeStatesWithChoice.set(originalState, true); + + if (state == wrh.getInternalInitialState()) { + chosenInitialComponentExitState = originalState; + chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState] + originalChoice; + } + ++state; } } From 8f2ef01a60dee8d2332eda00962fae4410eeed78 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 21 Nov 2025 10:02:58 +0100 Subject: [PATCH 059/102] formatting --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 2d43f1557e..814d893989 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -332,8 +332,7 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc storm::storage::BitVector const& maybeStatesWithoutChoice, storm::storage::BitVector const& maybeStatesWithChoice, std::vector const& stateToFinalEc, NormalFormData const& normalForm, uint64_t initialComponentIndex, storm::storage::BitVector const& initialComponentExitStates, storm::storage::BitVector const& initialComponentExitRows, - uint64_t chosenInitialComponentExitState, - uint64_t chosenInitialComponentExit) { + uint64_t chosenInitialComponentExitState, uint64_t chosenInitialComponentExit) { // Compute the EC stay choices for the states in maybeStatesWithChoice storm::storage::BitVector ecStayChoices(transitionMatrix.getRowCount(), false); storm::storage::BitVector initialComponentStates(transitionMatrix.getRowGroupCount(), false); @@ -461,7 +460,6 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc } } - storm::storage::BitVector exitStateBitvector(transitionMatrix.getRowGroupCount(), false); exitStateBitvector.set(chosenInitialComponentExitState, true); @@ -677,8 +675,8 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, - stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitStates, initialComponentExitRows, chosenInitialComponentExitState, - chosenInitialComponentExit); + stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitStates, initialComponentExitRows, + chosenInitialComponentExitState, chosenInitialComponentExit); auto finalResult = ResultReturnType(result.initialStateValue, std::move(scheduler)); From c19f2dbfd65a99bad95f948d710de2408daceb18 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 14:27:01 +0100 Subject: [PATCH 060/102] Add condition label to monitor verifier --- src/storm-pomdp/generator/GenerateMonitorVerifier.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index 28dd98e5b2..bd684495ba 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -304,6 +304,10 @@ std::shared_ptr> GenerateMonitorVerifier:: stateLabeling.addLabel("stop", storm::storage::BitVector(numberOfStates)); stateLabeling.addLabelToState("stop", stopIndex); + stateLabeling.addLabel("condition", storm::storage::BitVector(numberOfStates)); + stateLabeling.addLabelToState("condition", goalIndex); + stateLabeling.addLabelToState("condition", stopIndex); + if (!options.useRejectionSampling) { stateLabeling.addLabel("sink", storm::storage::BitVector(numberOfStates)); stateLabeling.addLabelToState("sink", rejectionIndex); From 2cc627db19a15a78e72339b23431fc8d04b5a7df Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:33:30 +0100 Subject: [PATCH 061/102] Add ValueType to ExplicitQualitativeCheckResult --- src/storm-cli-utilities/model-handling.h | 20 +-- .../api/counterexamples.cpp | 2 +- .../MILPMinimalLabelSetGenerator.h | 6 +- .../SMTMinimalLabelSetGenerator.h | 6 +- .../modelchecker/DFTModelChecker.cpp | 2 +- src/storm-pars-cli/sampling.h | 2 +- src/storm-pars-cli/solutionFunctions.h | 2 +- src/storm-pars/analysis/OrderExtender.cpp | 6 +- ...rseDerivativeInstantiationModelChecker.cpp | 8 +- .../SparseDtmcInstantiationModelChecker.cpp | 2 +- .../SparseMdpInstantiationModelChecker.cpp | 2 +- ...SparseDtmcParameterLiftingModelChecker.cpp | 10 +- .../SparseMdpParameterLiftingModelChecker.cpp | 10 +- .../SparseParameterLiftingModelChecker.cpp | 12 +- ...tingSparseParameterLiftingModelChecker.cpp | 4 +- .../SparseParametricDtmcSimplifier.cpp | 10 +- .../SparseParametricMdpSimplifier.cpp | 10 +- .../analysis/PermissiveSchedulers.cpp | 10 +- src/storm-pomdp-cli/storm-pomdp.cpp | 2 +- .../analysis/FormulaInformation.cpp | 2 +- .../analysis/QualitativeAnalysisOnGraphs.cpp | 2 +- .../GlobalPomdpMecChoiceEliminator.cpp | 2 +- src/storm/api/export.h | 3 +- .../modelchecker/AbstractModelChecker.cpp | 2 +- .../csl/SparseCtmcCslModelChecker.cpp | 26 ++-- .../SparseMarkovAutomatonCslModelChecker.cpp | 22 ++-- .../SparseCbAchievabilityQuery.cpp | 2 +- ...eterministicSchedsAchievabilityChecker.cpp | 4 +- .../DeterministicSchedsObjectiveHelper.cpp | 2 +- .../pcaa/SparsePcaaAchievabilityQuery.cpp | 3 +- .../pcaa/SparsePcaaQuantitativeQuery.cpp | 3 +- .../SparseMultiObjectivePreprocessor.cpp | 30 ++--- .../prctl/HybridMdpPrctlModelChecker.cpp | 2 +- .../prctl/SparseDtmcPrctlModelChecker.cpp | 30 ++--- .../prctl/SparseMdpPrctlModelChecker.cpp | 34 ++--- .../helper/rewardbounded/ProductModel.cpp | 10 +- .../SparsePropositionalModelChecker.cpp | 6 +- .../SparseDtmcEliminationModelChecker.cpp | 22 ++-- .../modelchecker/results/CheckResult.cpp | 22 +++- src/storm/modelchecker/results/CheckResult.h | 8 +- .../ExplicitParetoCurveCheckResult.cpp | 4 +- .../ExplicitQualitativeCheckResult.cpp | 117 +++++++++++++----- .../results/ExplicitQualitativeCheckResult.h | 6 + .../ExplicitQuantitativeCheckResult.cpp | 12 +- .../results/ExplicitQuantitativeCheckResult.h | 3 +- .../results/LexicographicCheckResult.cpp | 4 +- .../BisimulationDecomposition.cpp | 4 +- src/storm/transformer/MemoryIncorporation.cpp | 3 +- .../analysis/MonotonicityCheckerTest.cpp | 10 +- .../storm-pars/analysis/OrderExtenderTest.cpp | 10 +- .../analysis/MilpPermissiveSchedulerTest.cpp | 4 +- .../analysis/SmtPermissiveSchedulerTest.cpp | 4 +- .../csl/CtmcCslModelCheckerTest.cpp | 2 +- .../csl/LraCtmcCslModelCheckerTest.cpp | 2 +- .../MarkovAutomatonCslModelCheckerTest.cpp | 2 +- ...ultiObjectiveSchedRestModelCheckerTest.cpp | 10 +- ...arseMaCbMultiObjectiveModelCheckerTest.cpp | 4 +- ...seMaPcaaMultiObjectiveModelCheckerTest.cpp | 6 +- ...rseMdpCbMultiObjectiveModelCheckerTest.cpp | 8 +- ...eMdpPcaaMultiObjectiveModelCheckerTest.cpp | 8 +- .../prctl/dtmc/DtmcPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/MdpPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/QuantileQueryTest.cpp | 2 +- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 4 +- 64 files changed, 340 insertions(+), 256 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 36094ae6d3..b05483688f 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -915,14 +915,14 @@ inline void printCounterexample(std::shared_ptr - requires(!std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { +requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, + SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template - requires(std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { +requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, + SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -978,8 +978,8 @@ inline void generateCounterexamples(std::shared_ptr const& sparseMode } template - requires(!storm::IsIntervalType) -void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { +requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, + storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1046,9 +1046,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template - requires(!storm::IsIntervalType) -void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { +requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, + storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; @@ -1314,7 +1314,7 @@ void verifyModel(std::shared_ptr> const& std::unique_ptr filter; if (filterForInitialStates) { - filter = std::make_unique(sparseModel->getInitialStates()); + filter = std::make_unique>(sparseModel->getInitialStates()); } else if (!states->isTrueFormula()) { // No need to apply filter if it is the formula 'true' filter = storm::api::verifyWithSparseEngine(mpi.env, sparseModel, storm::api::createTask(states, false)); } diff --git a/src/storm-counterexamples/api/counterexamples.cpp b/src/storm-counterexamples/api/counterexamples.cpp index 6738bf2239..af0104a901 100644 --- a/src/storm-counterexamples/api/counterexamples.cpp +++ b/src/storm-counterexamples/api/counterexamples.cpp @@ -45,7 +45,7 @@ std::shared_ptr computeKShortestPathCoun storm::logic::EventuallyFormula const& eventuallyFormula = subformula.asEventuallyFormula(); std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); // Check if counterexample is even possible storm::storage::BitVector phiStates(model->getNumberOfStates(), true); diff --git a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h index cdd057d069..e14a490411 100644 --- a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h @@ -1023,8 +1023,8 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); phiStates = leftQualitativeResult.getTruthValuesVector(); psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -1033,7 +1033,7 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); phiStates = storm::storage::BitVector(mdp.getNumberOfStates(), true); psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h index 4cf453c738..5a837289ae 100644 --- a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h @@ -2157,8 +2157,8 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); result.phiStates = leftQualitativeResult.getTruthValuesVector(); result.psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -2167,7 +2167,7 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); result.phiStates = storm::storage::BitVector(model.getNumberOfStates(), true); result.psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-dft/modelchecker/DFTModelChecker.cpp b/src/storm-dft/modelchecker/DFTModelChecker.cpp index 17741c2f28..365252e0b9 100644 --- a/src/storm-dft/modelchecker/DFTModelChecker.cpp +++ b/src/storm-dft/modelchecker/DFTModelChecker.cpp @@ -461,7 +461,7 @@ std::vector DFTModelChecker::checkModel(std::shared_ptr(model, storm::api::createTask(property, true))); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); ValueType resultValue = result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second; results.push_back(resultValue); } else { diff --git a/src/storm-pars-cli/sampling.h b/src/storm-pars-cli/sampling.h index b7ade2ffa2..23aebd4162 100644 --- a/src/storm-pars-cli/sampling.h +++ b/src/storm-pars-cli/sampling.h @@ -115,7 +115,7 @@ void verifyPropertiesAtSamplePoints(ModelType const& model, cli::SymbolicInput c valuationWatch.stop(); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); } printInitialStatesResult(result, &valuationWatch, &valuation); diff --git a/src/storm-pars-cli/solutionFunctions.h b/src/storm-pars-cli/solutionFunctions.h index 294c50c56b..8c74e278ff 100644 --- a/src/storm-pars-cli/solutionFunctions.h +++ b/src/storm-pars-cli/solutionFunctions.h @@ -31,7 +31,7 @@ void computeSolutionFunctionsWithSparseEngine(std::shared_ptr result = storm::api::verifyWithSparseEngine(model, storm::api::createTask(formula, true)); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); } return result; }, diff --git a/src/storm-pars/analysis/OrderExtender.cpp b/src/storm-pars/analysis/OrderExtender.cpp index 10f82ef8a9..b866ef19fd 100644 --- a/src/storm-pars/analysis/OrderExtender.cpp +++ b/src/storm-pars/analysis/OrderExtender.cpp @@ -102,16 +102,16 @@ std::shared_ptr OrderExtender::getBottomTopOrder assert(formula->isProbabilityOperatorFormula()); if (formula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { phiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } else { assert(formula->asProbabilityOperatorFormula().getSubformula().isEventuallyFormula()); phiStates = storage::BitVector(numberOfStates, true); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } // Get the maybeStates diff --git a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp index 5bf5ec4f12..ce1ae41f60 100644 --- a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp +++ b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp @@ -143,20 +143,20 @@ void SparseDerivativeInstantiationModelChecker::spec if (this->currentFormula->isRewardOperatorFormula()) { auto subformula = modelchecker::CheckTask( this->currentFormula->asRewardOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { if (this->currentFormula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { auto rightSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()); auto leftSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()); - target = propositionalChecker.check(rightSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); - avoid = propositionalChecker.check(leftSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); avoid.complement(); } else { auto subformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } } initialStateModel = model.getStates("init").getNextSetIndex(0); diff --git a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp index 4e1309e3f5..61746fd785 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp @@ -181,7 +181,7 @@ std::unique_ptr SparseDtmcInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp index e42edf2233..3031c0a1cc 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp @@ -220,7 +220,7 @@ std::unique_ptr SparseMdpInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 189a399684..b2ccc14428 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -119,9 +119,9 @@ void SparseDtmcParameterLiftingModelChecker::spec propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -162,9 +162,9 @@ void SparseDtmcParameterLiftingModelChecker::spec propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -209,7 +209,7 @@ void SparseDtmcParameterLiftingModelChecker::spec STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index a6ee8d67de..e386be4218 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -108,9 +108,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -151,9 +151,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -202,7 +202,7 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp index 75735e7afd..c0c2c4ac43 100644 --- a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp @@ -76,7 +76,7 @@ RegionResult SparseParameterLiftingModelChecker:: if (hypothesis == RegionResultHypothesis::Unknown && result == RegionResult::Unknown) { result = getInstantiationChecker() .check(env, region.getCenterPoint()) - ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()] + ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()] ? RegionResult::CenterSat : RegionResult::CenterViolated; } @@ -123,7 +123,7 @@ RegionResult SparseParameterLiftingModelChecker:: // Check for result if (existsSat && getInstantiationCheckerSAT() .check(env, valuationToCheckSat) - ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { STORM_LOG_INFO("Region " << region << " is AllSat, discovered with instantiation checker on " << valuationToCheckSat << " and help of monotonicity\n"); RegionModelChecker::numberOfRegionsKnownThroughMonotonicity++; @@ -132,7 +132,7 @@ RegionResult SparseParameterLiftingModelChecker:: if (existsViolated && !getInstantiationCheckerVIO() .check(env, valuationToCheckViolated) - ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { STORM_LOG_INFO("Region " << region << " is AllViolated, discovered with instantiation checker on " << valuationToCheckViolated << " and help of monotonicity\n"); RegionModelChecker::numberOfRegionsKnownThroughMonotonicity++; @@ -150,7 +150,7 @@ RegionResult SparseParameterLiftingModelChecker:: ? storm::solver::OptimizationDirection::Minimize : storm::solver::OptimizationDirection::Maximize; auto checkResult = this->check(env, region, parameterOptimizationDirection, localMonotonicityResult); - if (checkResult->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (checkResult->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { result = RegionResult::AllSat; } else if (sampleVerticesOfRegion) { result = sampleVertices(env, region, result); @@ -161,7 +161,7 @@ RegionResult SparseParameterLiftingModelChecker:: ? storm::solver::OptimizationDirection::Maximize : storm::solver::OptimizationDirection::Minimize; auto checkResult = this->check(env, region, parameterOptimizationDirection, localMonotonicityResult); - if (!checkResult->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (!checkResult->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { result = RegionResult::AllViolated; } else if (sampleVerticesOfRegion) { result = sampleVertices(env, region, result); @@ -188,7 +188,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto vertices = region.getVerticesOfRegion(region.getVariables()); auto vertexIt = vertices.begin(); while (vertexIt != vertices.end() && !(hasSatPoint && hasViolatedPoint)) { - if (getInstantiationChecker().check(env, *vertexIt)->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (getInstantiationChecker().check(env, *vertexIt)->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { hasSatPoint = true; } else { hasViolatedPoint = true; diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp index f4857ae534..b812b789a6 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp @@ -47,7 +47,7 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + ->template asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; bool preciseResultAgrees = preciseResult == (currentResult == RegionResult::AllSat); if (!preciseResultAgrees) { @@ -60,7 +60,7 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + ->template asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; if (preciseResult && parameterOptDir == getPreciseChecker().getCurrentCheckTask().getOptimizationDirection()) { currentResult = RegionResult::AllSat; } else if (!preciseResult && parameterOptDir == storm::solver::invert(getPreciseChecker().getCurrentCheckTask().getOptimizationDirection())) { diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index 7258cbb5b2..ea66d7728e 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -30,9 +30,9 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -97,10 +97,10 @@ bool SparseParametricDtmcSimplifier::simplifyForBoundedUntilPro return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = storm::utility::graph::performProbGreater0(this->originalModel.getBackwardTransitions(), phiStates, psiStates, true, upperStepBound); @@ -152,7 +152,7 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 375690682f..4026d9dcfb 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -35,9 +35,9 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -121,10 +121,10 @@ bool SparseParametricMdpSimplifier::simplifyForBoundedUntilProb return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = minimizing ? storm::utility::graph::performProbGreater0A(this->originalModel.getTransitionMatrix(), @@ -182,7 +182,7 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm-permissive/analysis/PermissiveSchedulers.cpp b/src/storm-permissive/analysis/PermissiveSchedulers.cpp index 5ce205bc4d..a73a11c45f 100644 --- a/src/storm-permissive/analysis/PermissiveSchedulers.cpp +++ b/src/storm-permissive/analysis/PermissiveSchedulers.cpp @@ -20,8 +20,9 @@ boost::optional> computePermissiveSchedulerViaMILP storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); @@ -49,8 +50,9 @@ boost::optional> computePermissiveSchedulerViaSMT( storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); diff --git a/src/storm-pomdp-cli/storm-pomdp.cpp b/src/storm-pomdp-cli/storm-pomdp.cpp index df96bb6001..8df716bf5c 100644 --- a/src/storm-pomdp-cli/storm-pomdp.cpp +++ b/src/storm-pomdp-cli/storm-pomdp.cpp @@ -279,7 +279,7 @@ bool performAnalysis(std::shared_ptr> co storm::api::createTask(formula.asSharedPointer(), true)); if (resultPtr) { auto result = resultPtr->template asExplicitQuantitativeCheckResult(); - result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); + result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); if (storm::utility::resources::isTerminate()) { STORM_PRINT_AND_LOG("\nResult till abort: "); } else { diff --git a/src/storm-pomdp/analysis/FormulaInformation.cpp b/src/storm-pomdp/analysis/FormulaInformation.cpp index 3b7ad31bbf..62aaee7078 100644 --- a/src/storm-pomdp/analysis/FormulaInformation.cpp +++ b/src/storm-pomdp/analysis/FormulaInformation.cpp @@ -114,7 +114,7 @@ template storm::storage::BitVector getStates(storm::logic::Formula const& propositionalFormula, bool formulaInverted, PomdpType const& pomdp) { storm::modelchecker::SparsePropositionalModelChecker mc(pomdp); auto checkResult = mc.check(propositionalFormula); - storm::storage::BitVector resultBitVector(checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector resultBitVector(checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); if (formulaInverted) { resultBitVector.complement(); } diff --git a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp index 3f0f71845c..5a9a6fcea5 100644 --- a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp +++ b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp @@ -202,7 +202,7 @@ storm::storage::BitVector QualitativeAnalysisOnGraphs::checkPropositi storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class QualitativeAnalysisOnGraphs; diff --git a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp index a357cc5917..a8f1f388a6 100644 --- a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp +++ b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp @@ -234,7 +234,7 @@ storm::storage::BitVector GlobalPomdpMecChoiceEliminator::checkPropos storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class GlobalPomdpMecChoiceEliminator; diff --git a/src/storm/api/export.h b/src/storm/api/export.h index c24ea4ce33..baff690a6b 100644 --- a/src/storm/api/export.h +++ b/src/storm/api/export.h @@ -115,7 +115,8 @@ inline void exportCheckResultToJson(std::shared_ptrisExplicitQualitativeCheckResult()) { - auto j = checkResult->asExplicitQualitativeCheckResult().toJson(model->getOptionalStateValuations(), model->getStateLabeling()); + auto j = checkResult->template asExplicitQualitativeCheckResult().template toJson(model->getOptionalStateValuations(), + model->getStateLabeling()); stream << storm::dumpJson(j); } else { STORM_LOG_THROW(checkResult->isExplicitQuantitativeCheckResult(), storm::exceptions::NotSupportedException, diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index f81331c3d2..6b42c5be6c 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -150,7 +150,7 @@ std::unique_ptr AbstractModelChecker::computeStateFormul std::unique_ptr resultPointer = this->check(env, checkTask.getFormula()); if (resultPointer->isExplicitQualitativeCheckResult()) { STORM_LOG_ASSERT(ModelType::Representation == storm::models::ModelRepresentation::Sparse, "Unexpected model type."); - return std::make_unique>(resultPointer->asExplicitQualitativeCheckResult()); + return std::make_unique>(resultPointer->template asExplicitQualitativeCheckResult()); } else { STORM_LOG_ASSERT(resultPointer->isSymbolicQualitativeCheckResult(), "Unexpected result type."); STORM_LOG_ASSERT(ModelType::Representation != storm::models::ModelRepresentation::Sparse, "Unexpected model type."); diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp index e996985a72..7de27fdba4 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -52,9 +52,9 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); ; - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported."); @@ -81,7 +81,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -92,7 +92,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), probabilisticTransitions, probabilisticTransitions.transpose(), @@ -106,8 +106,8 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), @@ -125,7 +125,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -143,7 +143,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -181,7 +181,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -205,7 +205,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(probabilisticTransitions, this->getModel().getExitRateVector()); @@ -231,7 +231,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -250,9 +250,9 @@ std::vector SparseCtmcCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); ; - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeAllTransientProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), diff --git a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index 203cbce8f1..f5aa67bc85 100644 --- a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -72,10 +72,10 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded and reward-bounded properties on MAs are not supported."); @@ -103,7 +103,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -116,7 +116,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -135,8 +135,8 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeUntilProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), @@ -157,7 +157,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -183,7 +183,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -205,7 +205,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute reachability rewards in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityRewards( @@ -247,7 +247,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute long-run average in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper( this->getModel().getTransitionMatrix(), this->getModel().getMarkovianStates(), this->getModel().getExitRates()); @@ -291,7 +291,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute expected times in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityTimes( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), diff --git a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp index 225b7b12f5..4bfd4de17f 100644 --- a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp @@ -34,7 +34,7 @@ template std::unique_ptr SparseCbAchievabilityQuery::check(Environment const& env) { bool result = this->checkAchievability(); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp index cedca9edfe..75bdfe5c8b 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp @@ -63,13 +63,13 @@ std::unique_ptr DeterministicSchedsAchievabilityCheckercheck(env, thresholdPolytope, eps); bool const isAchievable = achievingPoint.has_value(); + using ValueType = typename SparseModelType::ValueType; if (isAchievable) { STORM_LOG_INFO( "Found achievable point: " << storm::utility::vector::toString(achievingPoint->first) << " ( approx. " << storm::utility::vector::toString(storm::utility::vector::convertNumericVector(achievingPoint->first)) << " )."); if (optimizingObjectiveIndex.has_value()) { - using ValueType = typename SparseModelType::ValueType; // Average between obtained lower- and upper bounds auto result = storm::utility::convertNumber(achievingPoint->first[*optimizingObjectiveIndex] + achievingPoint->second); @@ -80,7 +80,7 @@ std::unique_ptr DeterministicSchedsAchievabilityChecker>(originalModelInitialState, result); } } - return std::make_unique(originalModelInitialState, isAchievable); + return std::make_unique>(originalModelInitialState, isAchievable); } template class DeterministicSchedsAchievabilityChecker, storm::RationalNumber>; diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp index 535f534b4a..f7d2d42b8d 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp @@ -39,7 +39,7 @@ storm::storage::BitVector evaluatePropositionalFormula(ModelType const& model, s auto checkResult = mc.check(formula); STORM_LOG_THROW(checkResult && checkResult->isExplicitQualitativeCheckResult(), storm::exceptions::UnexpectedException, "Unexpected type of check result for subformula " << formula << "."); - return checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp index 9271fe33e6..562f4dbfc5 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp @@ -51,7 +51,8 @@ std::unique_ptr SparsePcaaAchievabilityQuerycheckAchievability(env); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp index c13762c22e..e4e613f69a 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp @@ -91,7 +91,8 @@ std::unique_ptr SparsePcaaQuantitativeQuery(new ExplicitQuantitativeCheckResult( this->originalModel.getInitialStates().getNextSetIndex(0), resultForOriginalModel)); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); } } diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 6eabbd6bda..1a51f2cafc 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -139,9 +139,9 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +151,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +161,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +181,7 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,13 +210,13 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); } } else if (opFormula->isLongRunAverageOperatorFormula()) { - auto lraStates = mc.check(pathFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lraStates = mc.check(pathFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Compute Sat(Forall F (Forall G not "lraStates")) auto forallGloballyNotLraStates = storm::utility::graph::performProb0A(backwardTransitions, ~lraStates, lraStates); absorbingStatesForSubformula = storm::utility::graph::performProb1A(model->getTransitionMatrix(), model->getNondeterministicChoiceIndices(), @@ -432,7 +432,7 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +445,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +455,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +542,7 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp index 344766e323..81815a9d85 100644 --- a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp @@ -176,7 +176,7 @@ std::unique_ptr HybridMdpPrctlModelChecker::checkMultiOb // Convert the explicit result if (explicitResult->isExplicitQualitativeCheckResult()) { - if (explicitResult->asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { + if (explicitResult->template asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { return std::unique_ptr(new storm::modelchecker::SymbolicQualitativeCheckResult( this->getModel().getReachableStates(), this->getModel().getInitialStates(), this->getModel().getManager().getBddOne())); } else { diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 1686bbe010..431039c622 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -92,8 +92,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper step bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -109,7 +109,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -121,8 +121,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -135,7 +135,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet()); @@ -151,7 +151,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -168,7 +168,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -236,7 +236,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -249,7 +249,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.getHint()); @@ -290,7 +290,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); @@ -320,8 +320,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -340,8 +340,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asReachabilityRewardFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 5930c02fdd..0033abb17f 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -139,8 +139,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to have discrete upper time bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -158,7 +158,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -172,8 +172,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -192,7 +192,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -215,7 +215,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -245,7 +245,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -276,14 +276,14 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); if constexpr (std::is_same_v) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { - return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, - this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), - leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + return storm::modelchecker::computeConditionalProbabilities( + env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, this->getModel().getTransitionMatrix(), + this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); } } @@ -363,7 +363,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -383,7 +383,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), @@ -446,7 +446,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); @@ -499,7 +499,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto ret = lexicographic::check(env, this->getModel(), checkTask, formulaChecker); std::unique_ptr result(new LexicographicCheckResult(ret.values, *this->getModel().getInitialStates().begin())); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 7bb836cc88..02b9e2f177 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -133,8 +133,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +155,7 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +426,9 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp index 094a2332cf..8fa08b56c7 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -35,9 +35,9 @@ std::unique_ptr SparsePropositionalModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::BooleanLiteralFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isTrueFormula()) { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); } } @@ -47,7 +47,7 @@ std::unique_ptr SparsePropositionalModelChecker::c storm::logic::AtomicLabelFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(model.hasLabel(stateFormula.getLabel()), storm::exceptions::InvalidPropertyException, "The property refers to unknown label '" << stateFormula.getLabel() << "'."); - return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); } template diff --git a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 43296a4d13..506f03b3ff 100644 --- a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -55,7 +55,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); - storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::SparseMatrix const& transitionMatrix = this->getModel().getTransitionMatrix(); uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); @@ -112,7 +112,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -177,7 +177,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -350,8 +350,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Start by determining the states that have a non-zero probability of reaching the target states within the // time bound. @@ -444,7 +444,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); + checkResult->filter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); } return checkResult; } @@ -457,8 +457,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); return computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, checkTask.isOnlyInitialStatesRelevantSet()); @@ -538,7 +538,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker subResultPointer = this->check(eventuallyFormula.getSubformula()); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& targetStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); @@ -650,8 +650,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - storm::storage::BitVector phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); // Do some sanity checks to establish some required properties. diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 8549ce26d0..c43c2cf441 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -82,12 +82,14 @@ bool CheckResult::isHybridQuantitativeCheckResult() const { return false; } -ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { + return dynamic_cast&>(*this); } -ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { + return dynamic_cast const&>(*this); } template @@ -188,6 +190,8 @@ template QuantitativeCheckResult const& CheckResult::asQuantitativeCheck template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; template LexicographicCheckResult& CheckResult::asLexicographicCheckResult(); @@ -221,6 +225,8 @@ template QuantitativeCheckResult const& CheckResult::asQu template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; @@ -228,6 +234,9 @@ template QuantitativeCheckResult const& CheckResult::as template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; @@ -235,5 +244,10 @@ template LexicographicCheckResult& CheckResult::asLexicog template LexicographicCheckResult const& CheckResult::asLexicographicCheckResult() const; #endif + +// Instantiation for storm::Interval (carl::Interval) +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/CheckResult.h b/src/storm/modelchecker/results/CheckResult.h index f46e1abcf9..c8ba918329 100644 --- a/src/storm/modelchecker/results/CheckResult.h +++ b/src/storm/modelchecker/results/CheckResult.h @@ -13,6 +13,7 @@ namespace modelchecker { class QualitativeCheckResult; template class QuantitativeCheckResult; +template class ExplicitQualitativeCheckResult; template @@ -77,8 +78,11 @@ class CheckResult { template QuantitativeCheckResult const& asQuantitativeCheckResult() const; - ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; + template + ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); + + template + ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; template ExplicitQuantitativeCheckResult& asExplicitQuantitativeCheckResult(); diff --git a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp index a9d59197a5..ac58ec1fc2 100644 --- a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp @@ -56,8 +56,8 @@ void ExplicitParetoCurveCheckResult::filter(QualitativeCheckResult co STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index f608a3065b..9404a7c355 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -3,53 +3,67 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/adapters/JsonAdapter.h" +#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/utility/macros.h" namespace storm { namespace modelchecker { -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { + +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { boost::get(truthValues)[state] = value; } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) + : truthValues(std::move(truthValues)) { // Intentionally left empty. } -std::unique_ptr ExplicitQualitativeCheckResult::clone() const { - return std::make_unique(this->truthValues); +template +std::unique_ptr ExplicitQualitativeCheckResult::clone() const { + return std::make_unique>(this->truthValues); } -void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, bool logicalAnd) { +template +void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, + bool logicalAnd) { STORM_LOG_THROW(second.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); STORM_LOG_THROW(first.isResultForAllStates() == second.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); - ExplicitQualitativeCheckResult const& secondCheckResult = static_cast(second); + ExplicitQualitativeCheckResult const& secondCheckResult = static_cast const&>(second); if (first.isResultForAllStates()) { if (logicalAnd) { boost::get(first.truthValues) &= boost::get(secondCheckResult.truthValues); @@ -78,17 +92,20 @@ void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitative } } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, true); return *this; } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, false); return *this; } -bool ExplicitQualitativeCheckResult::existsTrue() const { +template +bool ExplicitQualitativeCheckResult::existsTrue() const { if (this->isResultForAllStates()) { return !boost::get(truthValues).empty(); } else { @@ -100,7 +117,9 @@ bool ExplicitQualitativeCheckResult::existsTrue() const { return false; } } -bool ExplicitQualitativeCheckResult::forallTrue() const { + +template +bool ExplicitQualitativeCheckResult::forallTrue() const { if (this->isResultForAllStates()) { return boost::get(truthValues).full(); } else { @@ -113,7 +132,8 @@ bool ExplicitQualitativeCheckResult::forallTrue() const { } } -uint64_t ExplicitQualitativeCheckResult::count() const { +template +uint64_t ExplicitQualitativeCheckResult::count() const { if (this->isResultForAllStates()) { return boost::get(truthValues).getNumberOfSetBits(); } else { @@ -127,7 +147,8 @@ uint64_t ExplicitQualitativeCheckResult::count() const { } } -bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { +template +bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { if (this->isResultForAllStates()) { return boost::get(truthValues).get(state); } else { @@ -138,15 +159,18 @@ bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_ty } } -ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { +template +typename ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { return boost::get(truthValues); } -ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { +template +typename ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { return boost::get(truthValues); } -void ExplicitQualitativeCheckResult::complement() { +template +void ExplicitQualitativeCheckResult::complement() { if (this->isResultForAllStates()) { boost::get(truthValues).complement(); } else { @@ -156,19 +180,23 @@ void ExplicitQualitativeCheckResult::complement() { } } -bool ExplicitQualitativeCheckResult::isExplicit() const { +template +bool ExplicitQualitativeCheckResult::isExplicit() const { return true; } -bool ExplicitQualitativeCheckResult::isResultForAllStates() const { +template +bool ExplicitQualitativeCheckResult::isResultForAllStates() const { return truthValues.which() == 0; } -bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { +template +bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { return true; } -std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { +template +std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { if (this->isResultForAllStates()) { vector_type const& vector = boost::get(truthValues); bool allTrue = vector.full(); @@ -211,11 +239,12 @@ std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) c return out; } -void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { +template +void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { @@ -259,9 +288,10 @@ void insertJsonEntry(storm::json& json, uint64_t const& id, bo json.push_back(std::move(entry)); } +template template -storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, - std::optional const& stateLabels) const { +storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, + std::optional const& stateLabels) const { storm::json result; if (this->isResultForAllStates()) { vector_type const& valuesAsVector = boost::get(truthValues); @@ -277,10 +307,33 @@ storm::json ExplicitQualitativeCheckResult::toJson(std::option return result; } -template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, - std::optional const&) const; -template storm::json ExplicitQualitativeCheckResult::toJson( +// Explicit template instantiations +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; + +#ifdef STORM_HAVE_CARL +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; +#endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 8e13acbef7..9e67d1b277 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -9,12 +9,15 @@ #include "storm/modelchecker/results/QualitativeCheckResult.h" #include "storm/models/sparse/StateLabeling.h" #include "storm/storage/BitVector.h" +#include "storm/storage/Scheduler.h" #include "storm/storage/sparse/StateType.h" #include "storm/storage/sparse/StateValuations.h" namespace storm { namespace modelchecker { + +template class ExplicitQualitativeCheckResult : public QualitativeCheckResult { public: typedef storm::storage::BitVector vector_type; @@ -69,6 +72,9 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { // The values of the quantitative check result. boost::variant truthValues; + + // An optional scheduler that accompanies the values. + boost::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 3464ee9381..278ef000b4 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -61,7 +61,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boos } template -ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { +ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { if (other.isResultForAllStates()) { storm::storage::BitVector const& bvValues = other.getTruthValuesVector(); @@ -73,7 +73,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(Expl values = newVector; } else { - ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); + typename ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); map_type newMap; for (auto const& e : bitMap) { @@ -109,8 +109,8 @@ void ExplicitQuantitativeCheckResult::filter(QualitativeCheckResult c STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { map_type newMap; @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } } diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index e9c9ac487d..125752ca14 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -16,6 +16,7 @@ namespace storm { namespace modelchecker { // Forward declaration +template class ExplicitQualitativeCheckResult; template @@ -39,7 +40,7 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult const& other); virtual ~ExplicitQuantitativeCheckResult() = default; diff --git a/src/storm/modelchecker/results/LexicographicCheckResult.cpp b/src/storm/modelchecker/results/LexicographicCheckResult.cpp index 027f21f3ef..0206554088 100644 --- a/src/storm/modelchecker/results/LexicographicCheckResult.cpp +++ b/src/storm/modelchecker/results/LexicographicCheckResult.cpp @@ -43,8 +43,8 @@ void LexicographicCheckResult::filter(QualitativeCheckResult const& f STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp index 4828c13ef7..2f3206ac29 100644 --- a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp +++ b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp @@ -160,8 +160,8 @@ void BisimulationDecomposition::Options::checkAndSetMe storm::modelchecker::SparsePropositionalModelChecker checker(model); std::unique_ptr phiStatesCheckResult = checker.check(*leftSubformula); std::unique_ptr psiStatesCheckResult = checker.check(*rightSubformula); - phiStates = phiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); - psiStates = psiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + phiStates = phiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = psiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { optimalityType = boost::none; } diff --git a/src/storm/transformer/MemoryIncorporation.cpp b/src/storm/transformer/MemoryIncorporation.cpp index a0d894e6a3..14554ec711 100644 --- a/src/storm/transformer/MemoryIncorporation.cpp +++ b/src/storm/transformer/MemoryIncorporation.cpp @@ -27,7 +27,8 @@ storm::storage::MemoryStructure getGoalMemory(SparseModelType const& model, stor "The subformula " << propositionalGoalStateFormula << " should be propositional."); storm::modelchecker::SparsePropositionalModelChecker mc(model); - storm::storage::BitVector goalStates = mc.check(propositionalGoalStateFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = + mc.check(propositionalGoalStateFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied for all initial states. In such a case the trivial memory structure suffices. if (model.getInitialStates().isSubsetOf(goalStates)) { diff --git a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp index ed641deee7..03e4fb5f67 100644 --- a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp @@ -55,7 +55,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -103,7 +103,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -152,7 +152,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -205,7 +205,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -259,7 +259,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/analysis/OrderExtenderTest.cpp b/src/test/storm-pars/analysis/OrderExtenderTest.cpp index f201d0276b..13c98eda25 100644 --- a/src/test/storm-pars/analysis/OrderExtenderTest.cpp +++ b/src/test/storm-pars/analysis/OrderExtenderTest.cpp @@ -146,7 +146,7 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -193,7 +193,7 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -270,7 +270,7 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -361,7 +361,7 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -414,7 +414,7 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp index 4f3d460275..05d8bb66fc 100644 --- a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp @@ -54,7 +54,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -62,7 +62,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); } diff --git a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp index a0cafe14c3..46362ad298 100644 --- a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp @@ -49,7 +49,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -57,7 +57,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); diff --git a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp index b205fbc634..f65a91c100 100644 --- a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp @@ -294,7 +294,7 @@ class CtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp index ea1f9c0056..619f0d0ef5 100644 --- a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp @@ -364,7 +364,7 @@ class LraCtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp index 4220981ab1..b58391fc9e 100644 --- a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp @@ -235,7 +235,7 @@ class MarkovAutomatonCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp index 755a60f403..42fd7aa01e 100644 --- a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp @@ -274,13 +274,13 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { @@ -293,7 +293,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } @@ -359,7 +359,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } ++formulaIndex; @@ -371,7 +371,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp index 03e6762797..2fe681ff98 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp @@ -44,9 +44,9 @@ TEST_F(SparseMaCbMultiObjectiveModelCheckerTest, server) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp index ee24093d2b..bda5ce430b 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp @@ -175,12 +175,12 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_achievability_3Obj std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) { @@ -213,7 +213,7 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_pareto_2Obj) { diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp index 306364575c..4eae82674a 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp @@ -45,11 +45,11 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { @@ -71,7 +71,7 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } /* This test takes a little bit too long ... @@ -90,6 +90,6 @@ formulas)->as>(); uint_fast64_ std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(*mdp, formulas[0]->asMultiObjectiveFormula()) ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } */ diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp index f92a5d9f1d..d955034649 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp @@ -231,11 +231,11 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, zeroconf) { @@ -307,7 +307,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, tiny_rewards_negative) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { @@ -331,7 +331,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, dpm) { diff --git a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp index cb3785ac62..ec626279fb 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp @@ -585,7 +585,7 @@ class DtmcPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp index 23cb02ea19..0b8b8f47de 100644 --- a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp @@ -591,7 +591,7 @@ class MdpPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp index b4d82e499f..a006e5edcb 100644 --- a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp @@ -167,7 +167,7 @@ class QuantileQueryTest : public ::testing::Test { std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) const { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } }; diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 27a9254a16..3d509f2fbc 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -17,11 +17,11 @@ std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, From 11f04499efbeb14e2762721406670128965eac66 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:33:30 +0100 Subject: [PATCH 062/102] Add ValueType to ExplicitQualitativeCheckResult --- src/storm-cli-utilities/model-handling.h | 20 +-- .../api/counterexamples.cpp | 2 +- .../MILPMinimalLabelSetGenerator.h | 6 +- .../SMTMinimalLabelSetGenerator.h | 6 +- .../modelchecker/DFTModelChecker.cpp | 2 +- src/storm-pars-cli/sampling.h | 2 +- src/storm-pars-cli/solutionFunctions.h | 2 +- src/storm-pars/analysis/OrderExtender.cpp | 6 +- ...rseDerivativeInstantiationModelChecker.cpp | 8 +- .../SparseDtmcInstantiationModelChecker.cpp | 2 +- .../SparseMdpInstantiationModelChecker.cpp | 2 +- ...SparseDtmcParameterLiftingModelChecker.cpp | 10 +- .../SparseMdpParameterLiftingModelChecker.cpp | 10 +- .../SparseParameterLiftingModelChecker.cpp | 12 +- ...tingSparseParameterLiftingModelChecker.cpp | 4 +- .../SparseParametricDtmcSimplifier.cpp | 10 +- .../SparseParametricMdpSimplifier.cpp | 10 +- .../analysis/PermissiveSchedulers.cpp | 10 +- src/storm-pomdp-cli/storm-pomdp.cpp | 2 +- .../analysis/FormulaInformation.cpp | 2 +- .../analysis/QualitativeAnalysisOnGraphs.cpp | 2 +- .../GlobalPomdpMecChoiceEliminator.cpp | 2 +- src/storm/api/export.h | 3 +- .../modelchecker/AbstractModelChecker.cpp | 2 +- .../csl/SparseCtmcCslModelChecker.cpp | 26 ++-- .../SparseMarkovAutomatonCslModelChecker.cpp | 22 ++-- .../SparseCbAchievabilityQuery.cpp | 2 +- ...eterministicSchedsAchievabilityChecker.cpp | 4 +- .../DeterministicSchedsObjectiveHelper.cpp | 2 +- .../pcaa/SparsePcaaAchievabilityQuery.cpp | 3 +- .../pcaa/SparsePcaaQuantitativeQuery.cpp | 3 +- .../SparseMultiObjectivePreprocessor.cpp | 30 ++--- .../prctl/HybridMdpPrctlModelChecker.cpp | 2 +- .../prctl/SparseDtmcPrctlModelChecker.cpp | 30 ++--- .../prctl/SparseMdpPrctlModelChecker.cpp | 34 ++--- .../helper/rewardbounded/ProductModel.cpp | 10 +- .../SparsePropositionalModelChecker.cpp | 6 +- .../SparseDtmcEliminationModelChecker.cpp | 22 ++-- .../modelchecker/results/CheckResult.cpp | 22 +++- src/storm/modelchecker/results/CheckResult.h | 8 +- .../ExplicitParetoCurveCheckResult.cpp | 4 +- .../ExplicitQualitativeCheckResult.cpp | 117 +++++++++++++----- .../results/ExplicitQualitativeCheckResult.h | 6 + .../ExplicitQuantitativeCheckResult.cpp | 12 +- .../results/ExplicitQuantitativeCheckResult.h | 3 +- .../results/LexicographicCheckResult.cpp | 4 +- .../BisimulationDecomposition.cpp | 4 +- src/storm/transformer/MemoryIncorporation.cpp | 3 +- .../analysis/MonotonicityCheckerTest.cpp | 10 +- .../storm-pars/analysis/OrderExtenderTest.cpp | 10 +- .../analysis/MilpPermissiveSchedulerTest.cpp | 4 +- .../analysis/SmtPermissiveSchedulerTest.cpp | 4 +- .../csl/CtmcCslModelCheckerTest.cpp | 2 +- .../csl/LraCtmcCslModelCheckerTest.cpp | 2 +- .../MarkovAutomatonCslModelCheckerTest.cpp | 2 +- ...ultiObjectiveSchedRestModelCheckerTest.cpp | 10 +- ...arseMaCbMultiObjectiveModelCheckerTest.cpp | 4 +- ...seMaPcaaMultiObjectiveModelCheckerTest.cpp | 6 +- ...rseMdpCbMultiObjectiveModelCheckerTest.cpp | 8 +- ...eMdpPcaaMultiObjectiveModelCheckerTest.cpp | 8 +- .../prctl/dtmc/DtmcPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/MdpPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/QuantileQueryTest.cpp | 2 +- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 4 +- 64 files changed, 340 insertions(+), 256 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 36094ae6d3..b05483688f 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -915,14 +915,14 @@ inline void printCounterexample(std::shared_ptr - requires(!std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { +requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, + SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template - requires(std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { +requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, + SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -978,8 +978,8 @@ inline void generateCounterexamples(std::shared_ptr const& sparseMode } template - requires(!storm::IsIntervalType) -void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { +requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, + storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1046,9 +1046,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template - requires(!storm::IsIntervalType) -void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { +requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, + storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; @@ -1314,7 +1314,7 @@ void verifyModel(std::shared_ptr> const& std::unique_ptr filter; if (filterForInitialStates) { - filter = std::make_unique(sparseModel->getInitialStates()); + filter = std::make_unique>(sparseModel->getInitialStates()); } else if (!states->isTrueFormula()) { // No need to apply filter if it is the formula 'true' filter = storm::api::verifyWithSparseEngine(mpi.env, sparseModel, storm::api::createTask(states, false)); } diff --git a/src/storm-counterexamples/api/counterexamples.cpp b/src/storm-counterexamples/api/counterexamples.cpp index 6738bf2239..af0104a901 100644 --- a/src/storm-counterexamples/api/counterexamples.cpp +++ b/src/storm-counterexamples/api/counterexamples.cpp @@ -45,7 +45,7 @@ std::shared_ptr computeKShortestPathCoun storm::logic::EventuallyFormula const& eventuallyFormula = subformula.asEventuallyFormula(); std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); // Check if counterexample is even possible storm::storage::BitVector phiStates(model->getNumberOfStates(), true); diff --git a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h index cdd057d069..e14a490411 100644 --- a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h @@ -1023,8 +1023,8 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); phiStates = leftQualitativeResult.getTruthValuesVector(); psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -1033,7 +1033,7 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); phiStates = storm::storage::BitVector(mdp.getNumberOfStates(), true); psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h index 4cf453c738..5a837289ae 100644 --- a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h @@ -2157,8 +2157,8 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); result.phiStates = leftQualitativeResult.getTruthValuesVector(); result.psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -2167,7 +2167,7 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); result.phiStates = storm::storage::BitVector(model.getNumberOfStates(), true); result.psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-dft/modelchecker/DFTModelChecker.cpp b/src/storm-dft/modelchecker/DFTModelChecker.cpp index 17741c2f28..365252e0b9 100644 --- a/src/storm-dft/modelchecker/DFTModelChecker.cpp +++ b/src/storm-dft/modelchecker/DFTModelChecker.cpp @@ -461,7 +461,7 @@ std::vector DFTModelChecker::checkModel(std::shared_ptr(model, storm::api::createTask(property, true))); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); ValueType resultValue = result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second; results.push_back(resultValue); } else { diff --git a/src/storm-pars-cli/sampling.h b/src/storm-pars-cli/sampling.h index b7ade2ffa2..23aebd4162 100644 --- a/src/storm-pars-cli/sampling.h +++ b/src/storm-pars-cli/sampling.h @@ -115,7 +115,7 @@ void verifyPropertiesAtSamplePoints(ModelType const& model, cli::SymbolicInput c valuationWatch.stop(); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); } printInitialStatesResult(result, &valuationWatch, &valuation); diff --git a/src/storm-pars-cli/solutionFunctions.h b/src/storm-pars-cli/solutionFunctions.h index 294c50c56b..8c74e278ff 100644 --- a/src/storm-pars-cli/solutionFunctions.h +++ b/src/storm-pars-cli/solutionFunctions.h @@ -31,7 +31,7 @@ void computeSolutionFunctionsWithSparseEngine(std::shared_ptr result = storm::api::verifyWithSparseEngine(model, storm::api::createTask(formula, true)); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); } return result; }, diff --git a/src/storm-pars/analysis/OrderExtender.cpp b/src/storm-pars/analysis/OrderExtender.cpp index 10f82ef8a9..b866ef19fd 100644 --- a/src/storm-pars/analysis/OrderExtender.cpp +++ b/src/storm-pars/analysis/OrderExtender.cpp @@ -102,16 +102,16 @@ std::shared_ptr OrderExtender::getBottomTopOrder assert(formula->isProbabilityOperatorFormula()); if (formula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { phiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } else { assert(formula->asProbabilityOperatorFormula().getSubformula().isEventuallyFormula()); phiStates = storage::BitVector(numberOfStates, true); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } // Get the maybeStates diff --git a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp index 5bf5ec4f12..ce1ae41f60 100644 --- a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp +++ b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp @@ -143,20 +143,20 @@ void SparseDerivativeInstantiationModelChecker::spec if (this->currentFormula->isRewardOperatorFormula()) { auto subformula = modelchecker::CheckTask( this->currentFormula->asRewardOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { if (this->currentFormula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { auto rightSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()); auto leftSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()); - target = propositionalChecker.check(rightSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); - avoid = propositionalChecker.check(leftSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); avoid.complement(); } else { auto subformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } } initialStateModel = model.getStates("init").getNextSetIndex(0); diff --git a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp index 4e1309e3f5..61746fd785 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp @@ -181,7 +181,7 @@ std::unique_ptr SparseDtmcInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp index e42edf2233..3031c0a1cc 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp @@ -220,7 +220,7 @@ std::unique_ptr SparseMdpInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 189a399684..b2ccc14428 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -119,9 +119,9 @@ void SparseDtmcParameterLiftingModelChecker::spec propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -162,9 +162,9 @@ void SparseDtmcParameterLiftingModelChecker::spec propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -209,7 +209,7 @@ void SparseDtmcParameterLiftingModelChecker::spec STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index a6ee8d67de..e386be4218 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -108,9 +108,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -151,9 +151,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -202,7 +202,7 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp index 75735e7afd..c0c2c4ac43 100644 --- a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp @@ -76,7 +76,7 @@ RegionResult SparseParameterLiftingModelChecker:: if (hypothesis == RegionResultHypothesis::Unknown && result == RegionResult::Unknown) { result = getInstantiationChecker() .check(env, region.getCenterPoint()) - ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()] + ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()] ? RegionResult::CenterSat : RegionResult::CenterViolated; } @@ -123,7 +123,7 @@ RegionResult SparseParameterLiftingModelChecker:: // Check for result if (existsSat && getInstantiationCheckerSAT() .check(env, valuationToCheckSat) - ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { STORM_LOG_INFO("Region " << region << " is AllSat, discovered with instantiation checker on " << valuationToCheckSat << " and help of monotonicity\n"); RegionModelChecker::numberOfRegionsKnownThroughMonotonicity++; @@ -132,7 +132,7 @@ RegionResult SparseParameterLiftingModelChecker:: if (existsViolated && !getInstantiationCheckerVIO() .check(env, valuationToCheckViolated) - ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { STORM_LOG_INFO("Region " << region << " is AllViolated, discovered with instantiation checker on " << valuationToCheckViolated << " and help of monotonicity\n"); RegionModelChecker::numberOfRegionsKnownThroughMonotonicity++; @@ -150,7 +150,7 @@ RegionResult SparseParameterLiftingModelChecker:: ? storm::solver::OptimizationDirection::Minimize : storm::solver::OptimizationDirection::Maximize; auto checkResult = this->check(env, region, parameterOptimizationDirection, localMonotonicityResult); - if (checkResult->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (checkResult->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { result = RegionResult::AllSat; } else if (sampleVerticesOfRegion) { result = sampleVertices(env, region, result); @@ -161,7 +161,7 @@ RegionResult SparseParameterLiftingModelChecker:: ? storm::solver::OptimizationDirection::Maximize : storm::solver::OptimizationDirection::Minimize; auto checkResult = this->check(env, region, parameterOptimizationDirection, localMonotonicityResult); - if (!checkResult->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (!checkResult->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { result = RegionResult::AllViolated; } else if (sampleVerticesOfRegion) { result = sampleVertices(env, region, result); @@ -188,7 +188,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto vertices = region.getVerticesOfRegion(region.getVariables()); auto vertexIt = vertices.begin(); while (vertexIt != vertices.end() && !(hasSatPoint && hasViolatedPoint)) { - if (getInstantiationChecker().check(env, *vertexIt)->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (getInstantiationChecker().check(env, *vertexIt)->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { hasSatPoint = true; } else { hasViolatedPoint = true; diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp index f4857ae534..b812b789a6 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp @@ -47,7 +47,7 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + ->template asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; bool preciseResultAgrees = preciseResult == (currentResult == RegionResult::AllSat); if (!preciseResultAgrees) { @@ -60,7 +60,7 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + ->template asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; if (preciseResult && parameterOptDir == getPreciseChecker().getCurrentCheckTask().getOptimizationDirection()) { currentResult = RegionResult::AllSat; } else if (!preciseResult && parameterOptDir == storm::solver::invert(getPreciseChecker().getCurrentCheckTask().getOptimizationDirection())) { diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index 7258cbb5b2..ea66d7728e 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -30,9 +30,9 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -97,10 +97,10 @@ bool SparseParametricDtmcSimplifier::simplifyForBoundedUntilPro return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = storm::utility::graph::performProbGreater0(this->originalModel.getBackwardTransitions(), phiStates, psiStates, true, upperStepBound); @@ -152,7 +152,7 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 375690682f..4026d9dcfb 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -35,9 +35,9 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -121,10 +121,10 @@ bool SparseParametricMdpSimplifier::simplifyForBoundedUntilProb return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = minimizing ? storm::utility::graph::performProbGreater0A(this->originalModel.getTransitionMatrix(), @@ -182,7 +182,7 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm-permissive/analysis/PermissiveSchedulers.cpp b/src/storm-permissive/analysis/PermissiveSchedulers.cpp index 5ce205bc4d..a73a11c45f 100644 --- a/src/storm-permissive/analysis/PermissiveSchedulers.cpp +++ b/src/storm-permissive/analysis/PermissiveSchedulers.cpp @@ -20,8 +20,9 @@ boost::optional> computePermissiveSchedulerViaMILP storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); @@ -49,8 +50,9 @@ boost::optional> computePermissiveSchedulerViaSMT( storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); diff --git a/src/storm-pomdp-cli/storm-pomdp.cpp b/src/storm-pomdp-cli/storm-pomdp.cpp index df96bb6001..8df716bf5c 100644 --- a/src/storm-pomdp-cli/storm-pomdp.cpp +++ b/src/storm-pomdp-cli/storm-pomdp.cpp @@ -279,7 +279,7 @@ bool performAnalysis(std::shared_ptr> co storm::api::createTask(formula.asSharedPointer(), true)); if (resultPtr) { auto result = resultPtr->template asExplicitQuantitativeCheckResult(); - result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); + result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); if (storm::utility::resources::isTerminate()) { STORM_PRINT_AND_LOG("\nResult till abort: "); } else { diff --git a/src/storm-pomdp/analysis/FormulaInformation.cpp b/src/storm-pomdp/analysis/FormulaInformation.cpp index 3b7ad31bbf..62aaee7078 100644 --- a/src/storm-pomdp/analysis/FormulaInformation.cpp +++ b/src/storm-pomdp/analysis/FormulaInformation.cpp @@ -114,7 +114,7 @@ template storm::storage::BitVector getStates(storm::logic::Formula const& propositionalFormula, bool formulaInverted, PomdpType const& pomdp) { storm::modelchecker::SparsePropositionalModelChecker mc(pomdp); auto checkResult = mc.check(propositionalFormula); - storm::storage::BitVector resultBitVector(checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector resultBitVector(checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); if (formulaInverted) { resultBitVector.complement(); } diff --git a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp index 3f0f71845c..5a9a6fcea5 100644 --- a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp +++ b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp @@ -202,7 +202,7 @@ storm::storage::BitVector QualitativeAnalysisOnGraphs::checkPropositi storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class QualitativeAnalysisOnGraphs; diff --git a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp index a357cc5917..a8f1f388a6 100644 --- a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp +++ b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp @@ -234,7 +234,7 @@ storm::storage::BitVector GlobalPomdpMecChoiceEliminator::checkPropos storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class GlobalPomdpMecChoiceEliminator; diff --git a/src/storm/api/export.h b/src/storm/api/export.h index c24ea4ce33..baff690a6b 100644 --- a/src/storm/api/export.h +++ b/src/storm/api/export.h @@ -115,7 +115,8 @@ inline void exportCheckResultToJson(std::shared_ptrisExplicitQualitativeCheckResult()) { - auto j = checkResult->asExplicitQualitativeCheckResult().toJson(model->getOptionalStateValuations(), model->getStateLabeling()); + auto j = checkResult->template asExplicitQualitativeCheckResult().template toJson(model->getOptionalStateValuations(), + model->getStateLabeling()); stream << storm::dumpJson(j); } else { STORM_LOG_THROW(checkResult->isExplicitQuantitativeCheckResult(), storm::exceptions::NotSupportedException, diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index f81331c3d2..6b42c5be6c 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -150,7 +150,7 @@ std::unique_ptr AbstractModelChecker::computeStateFormul std::unique_ptr resultPointer = this->check(env, checkTask.getFormula()); if (resultPointer->isExplicitQualitativeCheckResult()) { STORM_LOG_ASSERT(ModelType::Representation == storm::models::ModelRepresentation::Sparse, "Unexpected model type."); - return std::make_unique>(resultPointer->asExplicitQualitativeCheckResult()); + return std::make_unique>(resultPointer->template asExplicitQualitativeCheckResult()); } else { STORM_LOG_ASSERT(resultPointer->isSymbolicQualitativeCheckResult(), "Unexpected result type."); STORM_LOG_ASSERT(ModelType::Representation != storm::models::ModelRepresentation::Sparse, "Unexpected model type."); diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp index e996985a72..7de27fdba4 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -52,9 +52,9 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); ; - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported."); @@ -81,7 +81,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -92,7 +92,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), probabilisticTransitions, probabilisticTransitions.transpose(), @@ -106,8 +106,8 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), @@ -125,7 +125,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -143,7 +143,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -181,7 +181,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -205,7 +205,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(probabilisticTransitions, this->getModel().getExitRateVector()); @@ -231,7 +231,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -250,9 +250,9 @@ std::vector SparseCtmcCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); ; - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeAllTransientProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), diff --git a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index 203cbce8f1..f5aa67bc85 100644 --- a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -72,10 +72,10 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded and reward-bounded properties on MAs are not supported."); @@ -103,7 +103,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -116,7 +116,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -135,8 +135,8 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeUntilProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), @@ -157,7 +157,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -183,7 +183,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -205,7 +205,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute reachability rewards in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityRewards( @@ -247,7 +247,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute long-run average in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper( this->getModel().getTransitionMatrix(), this->getModel().getMarkovianStates(), this->getModel().getExitRates()); @@ -291,7 +291,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute expected times in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityTimes( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), diff --git a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp index 225b7b12f5..4bfd4de17f 100644 --- a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp @@ -34,7 +34,7 @@ template std::unique_ptr SparseCbAchievabilityQuery::check(Environment const& env) { bool result = this->checkAchievability(); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp index cedca9edfe..75bdfe5c8b 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp @@ -63,13 +63,13 @@ std::unique_ptr DeterministicSchedsAchievabilityCheckercheck(env, thresholdPolytope, eps); bool const isAchievable = achievingPoint.has_value(); + using ValueType = typename SparseModelType::ValueType; if (isAchievable) { STORM_LOG_INFO( "Found achievable point: " << storm::utility::vector::toString(achievingPoint->first) << " ( approx. " << storm::utility::vector::toString(storm::utility::vector::convertNumericVector(achievingPoint->first)) << " )."); if (optimizingObjectiveIndex.has_value()) { - using ValueType = typename SparseModelType::ValueType; // Average between obtained lower- and upper bounds auto result = storm::utility::convertNumber(achievingPoint->first[*optimizingObjectiveIndex] + achievingPoint->second); @@ -80,7 +80,7 @@ std::unique_ptr DeterministicSchedsAchievabilityChecker>(originalModelInitialState, result); } } - return std::make_unique(originalModelInitialState, isAchievable); + return std::make_unique>(originalModelInitialState, isAchievable); } template class DeterministicSchedsAchievabilityChecker, storm::RationalNumber>; diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp index 535f534b4a..f7d2d42b8d 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp @@ -39,7 +39,7 @@ storm::storage::BitVector evaluatePropositionalFormula(ModelType const& model, s auto checkResult = mc.check(formula); STORM_LOG_THROW(checkResult && checkResult->isExplicitQualitativeCheckResult(), storm::exceptions::UnexpectedException, "Unexpected type of check result for subformula " << formula << "."); - return checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp index 9271fe33e6..562f4dbfc5 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp @@ -51,7 +51,8 @@ std::unique_ptr SparsePcaaAchievabilityQuerycheckAchievability(env); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp index c13762c22e..e4e613f69a 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp @@ -91,7 +91,8 @@ std::unique_ptr SparsePcaaQuantitativeQuery(new ExplicitQuantitativeCheckResult( this->originalModel.getInitialStates().getNextSetIndex(0), resultForOriginalModel)); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); } } diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 6eabbd6bda..1a51f2cafc 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -139,9 +139,9 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +151,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +161,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +181,7 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,13 +210,13 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); } } else if (opFormula->isLongRunAverageOperatorFormula()) { - auto lraStates = mc.check(pathFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lraStates = mc.check(pathFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Compute Sat(Forall F (Forall G not "lraStates")) auto forallGloballyNotLraStates = storm::utility::graph::performProb0A(backwardTransitions, ~lraStates, lraStates); absorbingStatesForSubformula = storm::utility::graph::performProb1A(model->getTransitionMatrix(), model->getNondeterministicChoiceIndices(), @@ -432,7 +432,7 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +445,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +455,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +542,7 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp index 344766e323..81815a9d85 100644 --- a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp @@ -176,7 +176,7 @@ std::unique_ptr HybridMdpPrctlModelChecker::checkMultiOb // Convert the explicit result if (explicitResult->isExplicitQualitativeCheckResult()) { - if (explicitResult->asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { + if (explicitResult->template asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { return std::unique_ptr(new storm::modelchecker::SymbolicQualitativeCheckResult( this->getModel().getReachableStates(), this->getModel().getInitialStates(), this->getModel().getManager().getBddOne())); } else { diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 1686bbe010..431039c622 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -92,8 +92,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper step bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -109,7 +109,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -121,8 +121,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -135,7 +135,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet()); @@ -151,7 +151,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -168,7 +168,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -236,7 +236,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -249,7 +249,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.getHint()); @@ -290,7 +290,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); @@ -320,8 +320,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -340,8 +340,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asReachabilityRewardFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 5930c02fdd..0033abb17f 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -139,8 +139,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to have discrete upper time bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -158,7 +158,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -172,8 +172,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -192,7 +192,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -215,7 +215,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -245,7 +245,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -276,14 +276,14 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); if constexpr (std::is_same_v) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { - return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, - this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), - leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + return storm::modelchecker::computeConditionalProbabilities( + env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, this->getModel().getTransitionMatrix(), + this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); } } @@ -363,7 +363,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -383,7 +383,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), @@ -446,7 +446,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); @@ -499,7 +499,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto ret = lexicographic::check(env, this->getModel(), checkTask, formulaChecker); std::unique_ptr result(new LexicographicCheckResult(ret.values, *this->getModel().getInitialStates().begin())); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 7bb836cc88..02b9e2f177 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -133,8 +133,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +155,7 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +426,9 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp index 094a2332cf..8fa08b56c7 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -35,9 +35,9 @@ std::unique_ptr SparsePropositionalModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::BooleanLiteralFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isTrueFormula()) { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); } } @@ -47,7 +47,7 @@ std::unique_ptr SparsePropositionalModelChecker::c storm::logic::AtomicLabelFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(model.hasLabel(stateFormula.getLabel()), storm::exceptions::InvalidPropertyException, "The property refers to unknown label '" << stateFormula.getLabel() << "'."); - return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); } template diff --git a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 43296a4d13..506f03b3ff 100644 --- a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -55,7 +55,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); - storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::SparseMatrix const& transitionMatrix = this->getModel().getTransitionMatrix(); uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); @@ -112,7 +112,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -177,7 +177,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -350,8 +350,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Start by determining the states that have a non-zero probability of reaching the target states within the // time bound. @@ -444,7 +444,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); + checkResult->filter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); } return checkResult; } @@ -457,8 +457,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); return computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, checkTask.isOnlyInitialStatesRelevantSet()); @@ -538,7 +538,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker subResultPointer = this->check(eventuallyFormula.getSubformula()); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& targetStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); @@ -650,8 +650,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - storm::storage::BitVector phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); // Do some sanity checks to establish some required properties. diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 8549ce26d0..c43c2cf441 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -82,12 +82,14 @@ bool CheckResult::isHybridQuantitativeCheckResult() const { return false; } -ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { + return dynamic_cast&>(*this); } -ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { + return dynamic_cast const&>(*this); } template @@ -188,6 +190,8 @@ template QuantitativeCheckResult const& CheckResult::asQuantitativeCheck template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; template LexicographicCheckResult& CheckResult::asLexicographicCheckResult(); @@ -221,6 +225,8 @@ template QuantitativeCheckResult const& CheckResult::asQu template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; @@ -228,6 +234,9 @@ template QuantitativeCheckResult const& CheckResult::as template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; @@ -235,5 +244,10 @@ template LexicographicCheckResult& CheckResult::asLexicog template LexicographicCheckResult const& CheckResult::asLexicographicCheckResult() const; #endif + +// Instantiation for storm::Interval (carl::Interval) +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/CheckResult.h b/src/storm/modelchecker/results/CheckResult.h index f46e1abcf9..c8ba918329 100644 --- a/src/storm/modelchecker/results/CheckResult.h +++ b/src/storm/modelchecker/results/CheckResult.h @@ -13,6 +13,7 @@ namespace modelchecker { class QualitativeCheckResult; template class QuantitativeCheckResult; +template class ExplicitQualitativeCheckResult; template @@ -77,8 +78,11 @@ class CheckResult { template QuantitativeCheckResult const& asQuantitativeCheckResult() const; - ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; + template + ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); + + template + ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; template ExplicitQuantitativeCheckResult& asExplicitQuantitativeCheckResult(); diff --git a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp index a9d59197a5..ac58ec1fc2 100644 --- a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp @@ -56,8 +56,8 @@ void ExplicitParetoCurveCheckResult::filter(QualitativeCheckResult co STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index f608a3065b..9404a7c355 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -3,53 +3,67 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/adapters/JsonAdapter.h" +#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/utility/macros.h" namespace storm { namespace modelchecker { -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { + +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { boost::get(truthValues)[state] = value; } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) + : truthValues(std::move(truthValues)) { // Intentionally left empty. } -std::unique_ptr ExplicitQualitativeCheckResult::clone() const { - return std::make_unique(this->truthValues); +template +std::unique_ptr ExplicitQualitativeCheckResult::clone() const { + return std::make_unique>(this->truthValues); } -void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, bool logicalAnd) { +template +void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, + bool logicalAnd) { STORM_LOG_THROW(second.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); STORM_LOG_THROW(first.isResultForAllStates() == second.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); - ExplicitQualitativeCheckResult const& secondCheckResult = static_cast(second); + ExplicitQualitativeCheckResult const& secondCheckResult = static_cast const&>(second); if (first.isResultForAllStates()) { if (logicalAnd) { boost::get(first.truthValues) &= boost::get(secondCheckResult.truthValues); @@ -78,17 +92,20 @@ void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitative } } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, true); return *this; } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, false); return *this; } -bool ExplicitQualitativeCheckResult::existsTrue() const { +template +bool ExplicitQualitativeCheckResult::existsTrue() const { if (this->isResultForAllStates()) { return !boost::get(truthValues).empty(); } else { @@ -100,7 +117,9 @@ bool ExplicitQualitativeCheckResult::existsTrue() const { return false; } } -bool ExplicitQualitativeCheckResult::forallTrue() const { + +template +bool ExplicitQualitativeCheckResult::forallTrue() const { if (this->isResultForAllStates()) { return boost::get(truthValues).full(); } else { @@ -113,7 +132,8 @@ bool ExplicitQualitativeCheckResult::forallTrue() const { } } -uint64_t ExplicitQualitativeCheckResult::count() const { +template +uint64_t ExplicitQualitativeCheckResult::count() const { if (this->isResultForAllStates()) { return boost::get(truthValues).getNumberOfSetBits(); } else { @@ -127,7 +147,8 @@ uint64_t ExplicitQualitativeCheckResult::count() const { } } -bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { +template +bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { if (this->isResultForAllStates()) { return boost::get(truthValues).get(state); } else { @@ -138,15 +159,18 @@ bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_ty } } -ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { +template +typename ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { return boost::get(truthValues); } -ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { +template +typename ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { return boost::get(truthValues); } -void ExplicitQualitativeCheckResult::complement() { +template +void ExplicitQualitativeCheckResult::complement() { if (this->isResultForAllStates()) { boost::get(truthValues).complement(); } else { @@ -156,19 +180,23 @@ void ExplicitQualitativeCheckResult::complement() { } } -bool ExplicitQualitativeCheckResult::isExplicit() const { +template +bool ExplicitQualitativeCheckResult::isExplicit() const { return true; } -bool ExplicitQualitativeCheckResult::isResultForAllStates() const { +template +bool ExplicitQualitativeCheckResult::isResultForAllStates() const { return truthValues.which() == 0; } -bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { +template +bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { return true; } -std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { +template +std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { if (this->isResultForAllStates()) { vector_type const& vector = boost::get(truthValues); bool allTrue = vector.full(); @@ -211,11 +239,12 @@ std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) c return out; } -void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { +template +void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { @@ -259,9 +288,10 @@ void insertJsonEntry(storm::json& json, uint64_t const& id, bo json.push_back(std::move(entry)); } +template template -storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, - std::optional const& stateLabels) const { +storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, + std::optional const& stateLabels) const { storm::json result; if (this->isResultForAllStates()) { vector_type const& valuesAsVector = boost::get(truthValues); @@ -277,10 +307,33 @@ storm::json ExplicitQualitativeCheckResult::toJson(std::option return result; } -template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, - std::optional const&) const; -template storm::json ExplicitQualitativeCheckResult::toJson( +// Explicit template instantiations +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; + +#ifdef STORM_HAVE_CARL +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; +#endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 8e13acbef7..9e67d1b277 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -9,12 +9,15 @@ #include "storm/modelchecker/results/QualitativeCheckResult.h" #include "storm/models/sparse/StateLabeling.h" #include "storm/storage/BitVector.h" +#include "storm/storage/Scheduler.h" #include "storm/storage/sparse/StateType.h" #include "storm/storage/sparse/StateValuations.h" namespace storm { namespace modelchecker { + +template class ExplicitQualitativeCheckResult : public QualitativeCheckResult { public: typedef storm::storage::BitVector vector_type; @@ -69,6 +72,9 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { // The values of the quantitative check result. boost::variant truthValues; + + // An optional scheduler that accompanies the values. + boost::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 3464ee9381..278ef000b4 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -61,7 +61,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boos } template -ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { +ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { if (other.isResultForAllStates()) { storm::storage::BitVector const& bvValues = other.getTruthValuesVector(); @@ -73,7 +73,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(Expl values = newVector; } else { - ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); + typename ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); map_type newMap; for (auto const& e : bitMap) { @@ -109,8 +109,8 @@ void ExplicitQuantitativeCheckResult::filter(QualitativeCheckResult c STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { map_type newMap; @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } } diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index e9c9ac487d..125752ca14 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -16,6 +16,7 @@ namespace storm { namespace modelchecker { // Forward declaration +template class ExplicitQualitativeCheckResult; template @@ -39,7 +40,7 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult const& other); virtual ~ExplicitQuantitativeCheckResult() = default; diff --git a/src/storm/modelchecker/results/LexicographicCheckResult.cpp b/src/storm/modelchecker/results/LexicographicCheckResult.cpp index 027f21f3ef..0206554088 100644 --- a/src/storm/modelchecker/results/LexicographicCheckResult.cpp +++ b/src/storm/modelchecker/results/LexicographicCheckResult.cpp @@ -43,8 +43,8 @@ void LexicographicCheckResult::filter(QualitativeCheckResult const& f STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp index 4828c13ef7..2f3206ac29 100644 --- a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp +++ b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp @@ -160,8 +160,8 @@ void BisimulationDecomposition::Options::checkAndSetMe storm::modelchecker::SparsePropositionalModelChecker checker(model); std::unique_ptr phiStatesCheckResult = checker.check(*leftSubformula); std::unique_ptr psiStatesCheckResult = checker.check(*rightSubformula); - phiStates = phiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); - psiStates = psiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + phiStates = phiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = psiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { optimalityType = boost::none; } diff --git a/src/storm/transformer/MemoryIncorporation.cpp b/src/storm/transformer/MemoryIncorporation.cpp index a0d894e6a3..14554ec711 100644 --- a/src/storm/transformer/MemoryIncorporation.cpp +++ b/src/storm/transformer/MemoryIncorporation.cpp @@ -27,7 +27,8 @@ storm::storage::MemoryStructure getGoalMemory(SparseModelType const& model, stor "The subformula " << propositionalGoalStateFormula << " should be propositional."); storm::modelchecker::SparsePropositionalModelChecker mc(model); - storm::storage::BitVector goalStates = mc.check(propositionalGoalStateFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = + mc.check(propositionalGoalStateFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied for all initial states. In such a case the trivial memory structure suffices. if (model.getInitialStates().isSubsetOf(goalStates)) { diff --git a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp index ed641deee7..03e4fb5f67 100644 --- a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp @@ -55,7 +55,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -103,7 +103,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -152,7 +152,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -205,7 +205,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -259,7 +259,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/analysis/OrderExtenderTest.cpp b/src/test/storm-pars/analysis/OrderExtenderTest.cpp index f201d0276b..13c98eda25 100644 --- a/src/test/storm-pars/analysis/OrderExtenderTest.cpp +++ b/src/test/storm-pars/analysis/OrderExtenderTest.cpp @@ -146,7 +146,7 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -193,7 +193,7 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -270,7 +270,7 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -361,7 +361,7 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -414,7 +414,7 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp index 4f3d460275..05d8bb66fc 100644 --- a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp @@ -54,7 +54,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -62,7 +62,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); } diff --git a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp index a0cafe14c3..46362ad298 100644 --- a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp @@ -49,7 +49,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -57,7 +57,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); diff --git a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp index b205fbc634..f65a91c100 100644 --- a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp @@ -294,7 +294,7 @@ class CtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp index ea1f9c0056..619f0d0ef5 100644 --- a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp @@ -364,7 +364,7 @@ class LraCtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp index 4220981ab1..b58391fc9e 100644 --- a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp @@ -235,7 +235,7 @@ class MarkovAutomatonCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp index 755a60f403..42fd7aa01e 100644 --- a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp @@ -274,13 +274,13 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { @@ -293,7 +293,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } @@ -359,7 +359,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } ++formulaIndex; @@ -371,7 +371,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp index 03e6762797..2fe681ff98 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp @@ -44,9 +44,9 @@ TEST_F(SparseMaCbMultiObjectiveModelCheckerTest, server) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp index ee24093d2b..bda5ce430b 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp @@ -175,12 +175,12 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_achievability_3Obj std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) { @@ -213,7 +213,7 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_pareto_2Obj) { diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp index 306364575c..4eae82674a 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp @@ -45,11 +45,11 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { @@ -71,7 +71,7 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } /* This test takes a little bit too long ... @@ -90,6 +90,6 @@ formulas)->as>(); uint_fast64_ std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(*mdp, formulas[0]->asMultiObjectiveFormula()) ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } */ diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp index f92a5d9f1d..d955034649 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp @@ -231,11 +231,11 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, zeroconf) { @@ -307,7 +307,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, tiny_rewards_negative) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { @@ -331,7 +331,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, dpm) { diff --git a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp index cb3785ac62..ec626279fb 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp @@ -585,7 +585,7 @@ class DtmcPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp index 23cb02ea19..0b8b8f47de 100644 --- a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp @@ -591,7 +591,7 @@ class MdpPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp index b4d82e499f..a006e5edcb 100644 --- a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp @@ -167,7 +167,7 @@ class QuantileQueryTest : public ::testing::Test { std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) const { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } }; diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 27a9254a16..3d509f2fbc 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -17,11 +17,11 @@ std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, From 2bad8c6a6d17d7e012d754a0fa467fe47a32356e Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:44:13 +0100 Subject: [PATCH 063/102] Remember scheduler from quantitative scheduler when applying bounds --- resources/3rdparty/l3pp | 1 + .../ExplicitQualitativeCheckResult.cpp | 31 +++++++++++++++++-- .../results/ExplicitQualitativeCheckResult.h | 11 +++++-- .../ExplicitQuantitativeCheckResult.cpp | 4 +-- 4 files changed, 40 insertions(+), 7 deletions(-) create mode 160000 resources/3rdparty/l3pp diff --git a/resources/3rdparty/l3pp b/resources/3rdparty/l3pp new file mode 160000 index 0000000000..e4f8d7fe6c --- /dev/null +++ b/resources/3rdparty/l3pp @@ -0,0 +1 @@ +Subproject commit e4f8d7fe6c328849aff34d2dfd6fd592c14070d5 diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 9404a7c355..f39ac58a74 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -41,13 +41,16 @@ ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm: } template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues, + boost::optional>> scheduler) + : truthValues(truthValues), scheduler(scheduler) { // Intentionally left empty. } template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) - : truthValues(std::move(truthValues)) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues, + boost::optional>> scheduler) + : truthValues(std::move(truthValues)), scheduler(scheduler) { // Intentionally left empty. } @@ -270,6 +273,28 @@ void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult co } } +template +bool ExplicitQualitativeCheckResult::hasScheduler() const { + return static_cast(scheduler); +} + +template +void ExplicitQualitativeCheckResult::setScheduler(std::unique_ptr>&& scheduler) { + this->scheduler = std::move(scheduler); +} + +template +storm::storage::Scheduler const& ExplicitQualitativeCheckResult::getScheduler() const { + STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + return *scheduler.get(); +} + +template +storm::storage::Scheduler& ExplicitQualitativeCheckResult::getScheduler() { + STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + return *scheduler.get(); +} + template void insertJsonEntry(storm::json& json, uint64_t const& id, bool value, std::optional const& stateValuations = std::nullopt, diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 9e67d1b277..14d781ef86 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -30,8 +30,10 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value); ExplicitQualitativeCheckResult(vector_type const& truthValues); ExplicitQualitativeCheckResult(vector_type&& truthValues); - ExplicitQualitativeCheckResult(boost::variant const& truthValues); - ExplicitQualitativeCheckResult(boost::variant&& truthValues); + ExplicitQualitativeCheckResult(boost::variant const& truthValues, + boost::optional>> scheduler = boost::none); + ExplicitQualitativeCheckResult(boost::variant&& truthValues, + boost::optional>> scheduler = boost::none); ExplicitQualitativeCheckResult(ExplicitQualitativeCheckResult const& other) = default; ExplicitQualitativeCheckResult& operator=(ExplicitQualitativeCheckResult const& other) = default; @@ -63,6 +65,11 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { virtual void filter(QualitativeCheckResult const& filter) override; + virtual bool hasScheduler() const override; + void setScheduler(std::unique_ptr>&& scheduler); + storm::storage::Scheduler const& getScheduler() const; + storm::storage::Scheduler& getScheduler(); + template storm::json toJson(std::optional const& stateValuations = std::nullopt, std::optional const& stateLabels = std::nullopt) const; diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 278ef000b4..f9dc8f2bef 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result), std::move(scheduler))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result), std::move(scheduler))); } } From e4ae96d22128b720caae9a38151db2abbff60a69 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:49:56 +0100 Subject: [PATCH 064/102] Export schedulers for qualitative models in the cli --- src/storm-cli-utilities/model-handling.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index b05483688f..51dbbd5172 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -1360,6 +1360,13 @@ void verifyModel(std::shared_ptr> const& auto const& paretoRes = result->template asExplicitParetoCurveCheckResult(); storm::api::exportParetoScheduler(sparseModel, paretoRes.getPoints(), paretoRes.getSchedulers(), schedulerExportPath.string()); } + } else if (result->isExplicitQualitativeCheckResult()) { + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export for interval models is not supported."); + } else { + storm::api::exportScheduler(sparseModel, result->template asExplicitQualitativeCheckResult().getScheduler(), + schedulerExportPath.string()); + } } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export not supported for this value type."); } From d342ac8548f9e7e289f1454df3aeeb05d6c1f255 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 16:56:08 +0100 Subject: [PATCH 065/102] run format --- src/storm-cli-utilities/model-handling.h | 18 +++---- ...SparseDtmcParameterLiftingModelChecker.cpp | 25 ++++++---- .../SparseMdpParameterLiftingModelChecker.cpp | 25 ++++++---- .../SparseParameterLiftingModelChecker.cpp | 4 +- ...tingSparseParameterLiftingModelChecker.cpp | 10 ++-- .../SparseParametricDtmcSimplifier.cpp | 15 +++--- .../SparseParametricMdpSimplifier.cpp | 15 +++--- src/storm/modelchecker/CheckTask.h | 8 ++-- .../helper/conditional/ConditionalHelper.h | 2 +- .../SparseMultiObjectivePreprocessor.cpp | 48 ++++++++++++------- .../helper/rewardbounded/ProductModel.cpp | 18 ++++--- src/storm/storage/Scheduler.h | 8 ++-- .../analysis/MonotonicityCheckerTest.cpp | 15 ++++-- .../storm-pars/analysis/OrderExtenderTest.cpp | 15 ++++-- 14 files changed, 138 insertions(+), 88 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 51dbbd5172..6498f2c4b2 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -915,14 +915,14 @@ inline void printCounterexample(std::shared_ptr -requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, - SymbolicInput const&) { + requires(!std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template -requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, - SymbolicInput const& input) { + requires(std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -978,8 +978,8 @@ requires(std::derived_from>) inl } template -requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, - storm::modelchecker::FilterType ft) { + requires(!storm::IsIntervalType) +void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1046,9 +1046,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template -requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, - storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { + requires(!storm::IsIntervalType) +void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index b2ccc14428..bd082aa013 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -118,10 +118,12 @@ void SparseDtmcParameterLiftingModelChecker::spec STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -161,10 +163,12 @@ void SparseDtmcParameterLiftingModelChecker::spec STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -208,8 +212,9 @@ void SparseDtmcParameterLiftingModelChecker::spec storm::modelchecker::SparsePropositionalModelChecker propositionalChecker(*this->parametricModel); STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(checkTask.getFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index e386be4218..b0ed7040a6 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -107,10 +107,12 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -150,10 +152,12 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -201,8 +205,9 @@ void SparseMdpParameterLiftingModelChecker::speci storm::modelchecker::SparsePropositionalModelChecker propositionalChecker(*this->parametricModel); STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(checkTask.getFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp index c0c2c4ac43..7a8b073480 100644 --- a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp @@ -188,7 +188,9 @@ RegionResult SparseParameterLiftingModelChecker:: auto vertices = region.getVerticesOfRegion(region.getVariables()); auto vertexIt = vertices.begin(); while (vertexIt != vertices.end() && !(hasSatPoint && hasViolatedPoint)) { - if (getInstantiationChecker().check(env, *vertexIt)->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (getInstantiationChecker() + .check(env, *vertexIt) + ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { hasSatPoint = true; } else { hasViolatedPoint = true; diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp index b812b789a6..c7ed4323d9 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp @@ -45,9 +45,10 @@ RegionResult ValidatingSparseParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + bool preciseResult = + getPreciseChecker() + .check(env, region, parameterOptDir) + ->template asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; bool preciseResultAgrees = preciseResult == (currentResult == RegionResult::AllSat); if (!preciseResultAgrees) { @@ -60,7 +61,8 @@ RegionResult ValidatingSparseParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + ->template asExplicitQualitativeCheckResult< + PreciseType>()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; if (preciseResult && parameterOptDir == getPreciseChecker().getCurrentCheckTask().getOptimizationDirection()) { currentResult = RegionResult::AllSat; } else if (!preciseResult && parameterOptDir == storm::solver::invert(getPreciseChecker().getCurrentCheckTask().getOptimizationDirection())) { diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index ea66d7728e..2910fa4881 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -29,10 +29,12 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit STORM_LOG_DEBUG("Can not simplify when Until-formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -151,8 +153,9 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew STORM_LOG_DEBUG("Can not simplify when reachability reward formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 4026d9dcfb..ed9ac1efbe 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -34,10 +34,12 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti STORM_LOG_DEBUG("Can not simplify when Until-formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -181,8 +183,9 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa STORM_LOG_DEBUG("Can not simplify when reachability reward formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm/modelchecker/CheckTask.h b/src/storm/modelchecker/CheckTask.h index 7dc4b28f86..8804b64a3d 100644 --- a/src/storm/modelchecker/CheckTask.h +++ b/src/storm/modelchecker/CheckTask.h @@ -129,11 +129,9 @@ class CheckTask { */ template CheckTask convertValueType() const { - - return CheckTask(this->formula, this->optimizationDirection, this->playerCoalition, this->rewardModel, this->onlyInitialStatesRelevant, - this->bound, this->qualitative, this->produceSchedulers, this->hint, this->robustUncertainty - ); - + return CheckTask(this->formula, this->optimizationDirection, this->playerCoalition, this->rewardModel, + this->onlyInitialStatesRelevant, this->bound, this->qualitative, this->produceSchedulers, this->hint, + this->robustUncertainty); } /*! diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.h b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h index 6303a6bd44..5596ebf115 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.h +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.h @@ -1,9 +1,9 @@ #pragma once #include -#include "storm/solver/SolveGoal.h" #include "storm/logic/ConditionalFormula.h" #include "storm/modelchecker/CheckTask.h" +#include "storm/solver/SolveGoal.h" namespace storm { class Environment; diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 1a51f2cafc..91dc7be1b2 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,10 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = + mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = + mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -138,10 +140,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector absorbingStatesForSubSubformula; for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); - auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i)) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i)) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +155,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +169,14 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +191,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,7 +221,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); @@ -432,7 +444,8 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = + mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +458,8 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = + mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +469,8 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = + mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +557,8 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = + mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 02b9e2f177..ccc196db4e 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -132,9 +132,12 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( for (auto dim : objectiveDimensions[objIndex]) { auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); - constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + constraintStates &= (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +158,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = + mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +430,11 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = + mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = + mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/storm/storage/Scheduler.h b/src/storm/storage/Scheduler.h index e1875212d5..8eb200b123 100644 --- a/src/storm/storage/Scheduler.h +++ b/src/storm/storage/Scheduler.h @@ -120,10 +120,10 @@ class Scheduler { boost::optional const& getMemoryStructure() const; /*! - * Retrieves a memoryless scheduler that corresponds to the given memory state. - * - * @param memoryState the memory state to fix - */ + * Retrieves a memoryless scheduler that corresponds to the given memory state. + * + * @param memoryState the memory state to fix + */ Scheduler getMemorylessSchedulerForMemoryState(uint64_t memoryState = 0) const; /*! diff --git a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp index 03e4fb5f67..b71c432fa6 100644 --- a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp @@ -55,7 +55,8 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -103,7 +104,8 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -152,7 +154,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -205,7 +208,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -259,7 +263,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/analysis/OrderExtenderTest.cpp b/src/test/storm-pars/analysis/OrderExtenderTest.cpp index 13c98eda25..1b8eccb82e 100644 --- a/src/test/storm-pars/analysis/OrderExtenderTest.cpp +++ b/src/test/storm-pars/analysis/OrderExtenderTest.cpp @@ -146,7 +146,8 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -193,7 +194,8 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -270,7 +272,8 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -361,7 +364,8 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -414,7 +418,8 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); From ede7c7bb303eb4628dd8b341d828dc29a74aa90f Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 17:02:13 +0100 Subject: [PATCH 066/102] Revert "Add ValueType to ExplicitQualitativeCheckResult" This reverts commit 2cc627db19a15a78e72339b23431fc8d04b5a7df. --- src/storm-cli-utilities/model-handling.h | 20 +-- .../api/counterexamples.cpp | 2 +- .../MILPMinimalLabelSetGenerator.h | 6 +- .../SMTMinimalLabelSetGenerator.h | 6 +- .../modelchecker/DFTModelChecker.cpp | 2 +- src/storm-pars-cli/sampling.h | 2 +- src/storm-pars-cli/solutionFunctions.h | 2 +- src/storm-pars/analysis/OrderExtender.cpp | 6 +- ...rseDerivativeInstantiationModelChecker.cpp | 8 +- .../SparseDtmcInstantiationModelChecker.cpp | 2 +- .../SparseMdpInstantiationModelChecker.cpp | 2 +- ...SparseDtmcParameterLiftingModelChecker.cpp | 10 +- .../SparseMdpParameterLiftingModelChecker.cpp | 10 +- .../SparseParameterLiftingModelChecker.cpp | 12 +- ...tingSparseParameterLiftingModelChecker.cpp | 4 +- .../SparseParametricDtmcSimplifier.cpp | 10 +- .../SparseParametricMdpSimplifier.cpp | 10 +- .../analysis/PermissiveSchedulers.cpp | 10 +- src/storm-pomdp-cli/storm-pomdp.cpp | 2 +- .../analysis/FormulaInformation.cpp | 2 +- .../analysis/QualitativeAnalysisOnGraphs.cpp | 2 +- .../GlobalPomdpMecChoiceEliminator.cpp | 2 +- src/storm/api/export.h | 3 +- .../modelchecker/AbstractModelChecker.cpp | 2 +- .../csl/SparseCtmcCslModelChecker.cpp | 26 ++-- .../SparseMarkovAutomatonCslModelChecker.cpp | 22 ++-- .../SparseCbAchievabilityQuery.cpp | 2 +- ...eterministicSchedsAchievabilityChecker.cpp | 4 +- .../DeterministicSchedsObjectiveHelper.cpp | 2 +- .../pcaa/SparsePcaaAchievabilityQuery.cpp | 3 +- .../pcaa/SparsePcaaQuantitativeQuery.cpp | 3 +- .../SparseMultiObjectivePreprocessor.cpp | 30 ++--- .../prctl/HybridMdpPrctlModelChecker.cpp | 2 +- .../prctl/SparseDtmcPrctlModelChecker.cpp | 30 ++--- .../prctl/SparseMdpPrctlModelChecker.cpp | 34 ++--- .../helper/rewardbounded/ProductModel.cpp | 10 +- .../SparsePropositionalModelChecker.cpp | 6 +- .../SparseDtmcEliminationModelChecker.cpp | 22 ++-- .../modelchecker/results/CheckResult.cpp | 22 +--- src/storm/modelchecker/results/CheckResult.h | 8 +- .../ExplicitParetoCurveCheckResult.cpp | 4 +- .../ExplicitQualitativeCheckResult.cpp | 117 +++++------------- .../results/ExplicitQualitativeCheckResult.h | 6 - .../ExplicitQuantitativeCheckResult.cpp | 12 +- .../results/ExplicitQuantitativeCheckResult.h | 3 +- .../results/LexicographicCheckResult.cpp | 4 +- .../BisimulationDecomposition.cpp | 4 +- src/storm/transformer/MemoryIncorporation.cpp | 3 +- .../analysis/MonotonicityCheckerTest.cpp | 10 +- .../storm-pars/analysis/OrderExtenderTest.cpp | 10 +- .../analysis/MilpPermissiveSchedulerTest.cpp | 4 +- .../analysis/SmtPermissiveSchedulerTest.cpp | 4 +- .../csl/CtmcCslModelCheckerTest.cpp | 2 +- .../csl/LraCtmcCslModelCheckerTest.cpp | 2 +- .../MarkovAutomatonCslModelCheckerTest.cpp | 2 +- ...ultiObjectiveSchedRestModelCheckerTest.cpp | 10 +- ...arseMaCbMultiObjectiveModelCheckerTest.cpp | 4 +- ...seMaPcaaMultiObjectiveModelCheckerTest.cpp | 6 +- ...rseMdpCbMultiObjectiveModelCheckerTest.cpp | 8 +- ...eMdpPcaaMultiObjectiveModelCheckerTest.cpp | 8 +- .../prctl/dtmc/DtmcPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/MdpPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/QuantileQueryTest.cpp | 2 +- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 4 +- 64 files changed, 256 insertions(+), 340 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index b05483688f..36094ae6d3 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -915,14 +915,14 @@ inline void printCounterexample(std::shared_ptr -requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, - SymbolicInput const&) { + requires(!std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template -requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, - SymbolicInput const& input) { + requires(std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -978,8 +978,8 @@ requires(std::derived_from>) inl } template -requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, - storm::modelchecker::FilterType ft) { + requires(!storm::IsIntervalType) +void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1046,9 +1046,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template -requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, - storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { + requires(!storm::IsIntervalType) +void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; @@ -1314,7 +1314,7 @@ void verifyModel(std::shared_ptr> const& std::unique_ptr filter; if (filterForInitialStates) { - filter = std::make_unique>(sparseModel->getInitialStates()); + filter = std::make_unique(sparseModel->getInitialStates()); } else if (!states->isTrueFormula()) { // No need to apply filter if it is the formula 'true' filter = storm::api::verifyWithSparseEngine(mpi.env, sparseModel, storm::api::createTask(states, false)); } diff --git a/src/storm-counterexamples/api/counterexamples.cpp b/src/storm-counterexamples/api/counterexamples.cpp index af0104a901..6738bf2239 100644 --- a/src/storm-counterexamples/api/counterexamples.cpp +++ b/src/storm-counterexamples/api/counterexamples.cpp @@ -45,7 +45,7 @@ std::shared_ptr computeKShortestPathCoun storm::logic::EventuallyFormula const& eventuallyFormula = subformula.asEventuallyFormula(); std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); // Check if counterexample is even possible storm::storage::BitVector phiStates(model->getNumberOfStates(), true); diff --git a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h index e14a490411..cdd057d069 100644 --- a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h @@ -1023,8 +1023,8 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); phiStates = leftQualitativeResult.getTruthValuesVector(); psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -1033,7 +1033,7 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); phiStates = storm::storage::BitVector(mdp.getNumberOfStates(), true); psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h index 5a837289ae..4cf453c738 100644 --- a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h @@ -2157,8 +2157,8 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); result.phiStates = leftQualitativeResult.getTruthValuesVector(); result.psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -2167,7 +2167,7 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); result.phiStates = storm::storage::BitVector(model.getNumberOfStates(), true); result.psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-dft/modelchecker/DFTModelChecker.cpp b/src/storm-dft/modelchecker/DFTModelChecker.cpp index 365252e0b9..17741c2f28 100644 --- a/src/storm-dft/modelchecker/DFTModelChecker.cpp +++ b/src/storm-dft/modelchecker/DFTModelChecker.cpp @@ -461,7 +461,7 @@ std::vector DFTModelChecker::checkModel(std::shared_ptr(model, storm::api::createTask(property, true))); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); ValueType resultValue = result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second; results.push_back(resultValue); } else { diff --git a/src/storm-pars-cli/sampling.h b/src/storm-pars-cli/sampling.h index 23aebd4162..b7ade2ffa2 100644 --- a/src/storm-pars-cli/sampling.h +++ b/src/storm-pars-cli/sampling.h @@ -115,7 +115,7 @@ void verifyPropertiesAtSamplePoints(ModelType const& model, cli::SymbolicInput c valuationWatch.stop(); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); } printInitialStatesResult(result, &valuationWatch, &valuation); diff --git a/src/storm-pars-cli/solutionFunctions.h b/src/storm-pars-cli/solutionFunctions.h index 8c74e278ff..294c50c56b 100644 --- a/src/storm-pars-cli/solutionFunctions.h +++ b/src/storm-pars-cli/solutionFunctions.h @@ -31,7 +31,7 @@ void computeSolutionFunctionsWithSparseEngine(std::shared_ptr result = storm::api::verifyWithSparseEngine(model, storm::api::createTask(formula, true)); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); } return result; }, diff --git a/src/storm-pars/analysis/OrderExtender.cpp b/src/storm-pars/analysis/OrderExtender.cpp index b866ef19fd..10f82ef8a9 100644 --- a/src/storm-pars/analysis/OrderExtender.cpp +++ b/src/storm-pars/analysis/OrderExtender.cpp @@ -102,16 +102,16 @@ std::shared_ptr OrderExtender::getBottomTopOrder assert(formula->isProbabilityOperatorFormula()); if (formula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { phiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()) - ->template asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector(); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()) - ->template asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector(); } else { assert(formula->asProbabilityOperatorFormula().getSubformula().isEventuallyFormula()); phiStates = storage::BitVector(numberOfStates, true); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->template asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector(); } // Get the maybeStates diff --git a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp index ce1ae41f60..5bf5ec4f12 100644 --- a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp +++ b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp @@ -143,20 +143,20 @@ void SparseDerivativeInstantiationModelChecker::spec if (this->currentFormula->isRewardOperatorFormula()) { auto subformula = modelchecker::CheckTask( this->currentFormula->asRewardOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { if (this->currentFormula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { auto rightSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()); auto leftSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()); - target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(rightSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + avoid = propositionalChecker.check(leftSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); avoid.complement(); } else { auto subformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); } } initialStateModel = model.getStates("init").getNextSetIndex(0); diff --git a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp index 61746fd785..4e1309e3f5 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp @@ -181,7 +181,7 @@ std::unique_ptr SparseDtmcInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp index 3031c0a1cc..e42edf2233 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp @@ -220,7 +220,7 @@ std::unique_ptr SparseMdpInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index b2ccc14428..189a399684 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -119,9 +119,9 @@ void SparseDtmcParameterLiftingModelChecker::spec propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -162,9 +162,9 @@ void SparseDtmcParameterLiftingModelChecker::spec propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -209,7 +209,7 @@ void SparseDtmcParameterLiftingModelChecker::spec STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index e386be4218..a6ee8d67de 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -108,9 +108,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -151,9 +151,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -202,7 +202,7 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp index c0c2c4ac43..75735e7afd 100644 --- a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp @@ -76,7 +76,7 @@ RegionResult SparseParameterLiftingModelChecker:: if (hypothesis == RegionResultHypothesis::Unknown && result == RegionResult::Unknown) { result = getInstantiationChecker() .check(env, region.getCenterPoint()) - ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()] + ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()] ? RegionResult::CenterSat : RegionResult::CenterViolated; } @@ -123,7 +123,7 @@ RegionResult SparseParameterLiftingModelChecker:: // Check for result if (existsSat && getInstantiationCheckerSAT() .check(env, valuationToCheckSat) - ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { STORM_LOG_INFO("Region " << region << " is AllSat, discovered with instantiation checker on " << valuationToCheckSat << " and help of monotonicity\n"); RegionModelChecker::numberOfRegionsKnownThroughMonotonicity++; @@ -132,7 +132,7 @@ RegionResult SparseParameterLiftingModelChecker:: if (existsViolated && !getInstantiationCheckerVIO() .check(env, valuationToCheckViolated) - ->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + ->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { STORM_LOG_INFO("Region " << region << " is AllViolated, discovered with instantiation checker on " << valuationToCheckViolated << " and help of monotonicity\n"); RegionModelChecker::numberOfRegionsKnownThroughMonotonicity++; @@ -150,7 +150,7 @@ RegionResult SparseParameterLiftingModelChecker:: ? storm::solver::OptimizationDirection::Minimize : storm::solver::OptimizationDirection::Maximize; auto checkResult = this->check(env, region, parameterOptimizationDirection, localMonotonicityResult); - if (checkResult->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (checkResult->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { result = RegionResult::AllSat; } else if (sampleVerticesOfRegion) { result = sampleVertices(env, region, result); @@ -161,7 +161,7 @@ RegionResult SparseParameterLiftingModelChecker:: ? storm::solver::OptimizationDirection::Maximize : storm::solver::OptimizationDirection::Minimize; auto checkResult = this->check(env, region, parameterOptimizationDirection, localMonotonicityResult); - if (!checkResult->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (!checkResult->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { result = RegionResult::AllViolated; } else if (sampleVerticesOfRegion) { result = sampleVertices(env, region, result); @@ -188,7 +188,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto vertices = region.getVerticesOfRegion(region.getVariables()); auto vertexIt = vertices.begin(); while (vertexIt != vertices.end() && !(hasSatPoint && hasViolatedPoint)) { - if (getInstantiationChecker().check(env, *vertexIt)->template asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { + if (getInstantiationChecker().check(env, *vertexIt)->asExplicitQualitativeCheckResult()[*this->parametricModel->getInitialStates().begin()]) { hasSatPoint = true; } else { hasViolatedPoint = true; diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp index b812b789a6..f4857ae534 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp @@ -47,7 +47,7 @@ RegionResult ValidatingSparseParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + ->asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; bool preciseResultAgrees = preciseResult == (currentResult == RegionResult::AllSat); if (!preciseResultAgrees) { @@ -60,7 +60,7 @@ RegionResult ValidatingSparseParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; + ->asExplicitQualitativeCheckResult()[*getPreciseChecker().getConsideredParametricModel().getInitialStates().begin()]; if (preciseResult && parameterOptDir == getPreciseChecker().getCurrentCheckTask().getOptimizationDirection()) { currentResult = RegionResult::AllSat; } else if (!preciseResult && parameterOptDir == storm::solver::invert(getPreciseChecker().getCurrentCheckTask().getOptimizationDirection())) { diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index ea66d7728e..7258cbb5b2 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -30,9 +30,9 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -97,10 +97,10 @@ bool SparseParametricDtmcSimplifier::simplifyForBoundedUntilPro return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->template asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->template asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = storm::utility::graph::performProbGreater0(this->originalModel.getBackwardTransitions(), phiStates, psiStates, true, upperStepBound); @@ -152,7 +152,7 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 4026d9dcfb..375690682f 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -35,9 +35,9 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -121,10 +121,10 @@ bool SparseParametricMdpSimplifier::simplifyForBoundedUntilProb return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->template asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->template asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = minimizing ? storm::utility::graph::performProbGreater0A(this->originalModel.getTransitionMatrix(), @@ -182,7 +182,7 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm-permissive/analysis/PermissiveSchedulers.cpp b/src/storm-permissive/analysis/PermissiveSchedulers.cpp index a73a11c45f..5ce205bc4d 100644 --- a/src/storm-permissive/analysis/PermissiveSchedulers.cpp +++ b/src/storm-permissive/analysis/PermissiveSchedulers.cpp @@ -20,9 +20,8 @@ boost::optional> computePermissiveSchedulerViaMILP storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) - ->template asExplicitQualitativeCheckResult() - .getTruthValuesVector(); + storm::storage::BitVector goalstates = + propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); @@ -50,9 +49,8 @@ boost::optional> computePermissiveSchedulerViaSMT( storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) - ->template asExplicitQualitativeCheckResult() - .getTruthValuesVector(); + storm::storage::BitVector goalstates = + propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); diff --git a/src/storm-pomdp-cli/storm-pomdp.cpp b/src/storm-pomdp-cli/storm-pomdp.cpp index 8df716bf5c..df96bb6001 100644 --- a/src/storm-pomdp-cli/storm-pomdp.cpp +++ b/src/storm-pomdp-cli/storm-pomdp.cpp @@ -279,7 +279,7 @@ bool performAnalysis(std::shared_ptr> co storm::api::createTask(formula.asSharedPointer(), true)); if (resultPtr) { auto result = resultPtr->template asExplicitQuantitativeCheckResult(); - result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); + result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); if (storm::utility::resources::isTerminate()) { STORM_PRINT_AND_LOG("\nResult till abort: "); } else { diff --git a/src/storm-pomdp/analysis/FormulaInformation.cpp b/src/storm-pomdp/analysis/FormulaInformation.cpp index 62aaee7078..3b7ad31bbf 100644 --- a/src/storm-pomdp/analysis/FormulaInformation.cpp +++ b/src/storm-pomdp/analysis/FormulaInformation.cpp @@ -114,7 +114,7 @@ template storm::storage::BitVector getStates(storm::logic::Formula const& propositionalFormula, bool formulaInverted, PomdpType const& pomdp) { storm::modelchecker::SparsePropositionalModelChecker mc(pomdp); auto checkResult = mc.check(propositionalFormula); - storm::storage::BitVector resultBitVector(checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector resultBitVector(checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); if (formulaInverted) { resultBitVector.complement(); } diff --git a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp index 5a9a6fcea5..3f0f71845c 100644 --- a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp +++ b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp @@ -202,7 +202,7 @@ storm::storage::BitVector QualitativeAnalysisOnGraphs::checkPropositi storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class QualitativeAnalysisOnGraphs; diff --git a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp index a8f1f388a6..a357cc5917 100644 --- a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp +++ b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp @@ -234,7 +234,7 @@ storm::storage::BitVector GlobalPomdpMecChoiceEliminator::checkPropos storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class GlobalPomdpMecChoiceEliminator; diff --git a/src/storm/api/export.h b/src/storm/api/export.h index baff690a6b..c24ea4ce33 100644 --- a/src/storm/api/export.h +++ b/src/storm/api/export.h @@ -115,8 +115,7 @@ inline void exportCheckResultToJson(std::shared_ptrisExplicitQualitativeCheckResult()) { - auto j = checkResult->template asExplicitQualitativeCheckResult().template toJson(model->getOptionalStateValuations(), - model->getStateLabeling()); + auto j = checkResult->asExplicitQualitativeCheckResult().toJson(model->getOptionalStateValuations(), model->getStateLabeling()); stream << storm::dumpJson(j); } else { STORM_LOG_THROW(checkResult->isExplicitQuantitativeCheckResult(), storm::exceptions::NotSupportedException, diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index 6b42c5be6c..f81331c3d2 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -150,7 +150,7 @@ std::unique_ptr AbstractModelChecker::computeStateFormul std::unique_ptr resultPointer = this->check(env, checkTask.getFormula()); if (resultPointer->isExplicitQualitativeCheckResult()) { STORM_LOG_ASSERT(ModelType::Representation == storm::models::ModelRepresentation::Sparse, "Unexpected model type."); - return std::make_unique>(resultPointer->template asExplicitQualitativeCheckResult()); + return std::make_unique>(resultPointer->asExplicitQualitativeCheckResult()); } else { STORM_LOG_ASSERT(resultPointer->isSymbolicQualitativeCheckResult(), "Unexpected result type."); STORM_LOG_ASSERT(ModelType::Representation != storm::models::ModelRepresentation::Sparse, "Unexpected model type."); diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 7de27fdba4..e996985a72 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -52,9 +52,9 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ; - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported."); @@ -81,7 +81,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -92,7 +92,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), probabilisticTransitions, probabilisticTransitions.transpose(), @@ -106,8 +106,8 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), @@ -125,7 +125,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -143,7 +143,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -181,7 +181,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -205,7 +205,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(probabilisticTransitions, this->getModel().getExitRateVector()); @@ -231,7 +231,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -250,9 +250,9 @@ std::vector SparseCtmcCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ; - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeAllTransientProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), diff --git a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index f5aa67bc85..203cbce8f1 100644 --- a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -72,10 +72,10 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded and reward-bounded properties on MAs are not supported."); @@ -103,7 +103,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -116,7 +116,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -135,8 +135,8 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeUntilProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), @@ -157,7 +157,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -183,7 +183,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -205,7 +205,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute reachability rewards in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityRewards( @@ -247,7 +247,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute long-run average in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper( this->getModel().getTransitionMatrix(), this->getModel().getMarkovianStates(), this->getModel().getExitRates()); @@ -291,7 +291,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute expected times in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityTimes( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), diff --git a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp index 4bfd4de17f..225b7b12f5 100644 --- a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp @@ -34,7 +34,7 @@ template std::unique_ptr SparseCbAchievabilityQuery::check(Environment const& env) { bool result = this->checkAchievability(); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp index 75bdfe5c8b..cedca9edfe 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp @@ -63,13 +63,13 @@ std::unique_ptr DeterministicSchedsAchievabilityCheckercheck(env, thresholdPolytope, eps); bool const isAchievable = achievingPoint.has_value(); - using ValueType = typename SparseModelType::ValueType; if (isAchievable) { STORM_LOG_INFO( "Found achievable point: " << storm::utility::vector::toString(achievingPoint->first) << " ( approx. " << storm::utility::vector::toString(storm::utility::vector::convertNumericVector(achievingPoint->first)) << " )."); if (optimizingObjectiveIndex.has_value()) { + using ValueType = typename SparseModelType::ValueType; // Average between obtained lower- and upper bounds auto result = storm::utility::convertNumber(achievingPoint->first[*optimizingObjectiveIndex] + achievingPoint->second); @@ -80,7 +80,7 @@ std::unique_ptr DeterministicSchedsAchievabilityChecker>(originalModelInitialState, result); } } - return std::make_unique>(originalModelInitialState, isAchievable); + return std::make_unique(originalModelInitialState, isAchievable); } template class DeterministicSchedsAchievabilityChecker, storm::RationalNumber>; diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp index f7d2d42b8d..535f534b4a 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp @@ -39,7 +39,7 @@ storm::storage::BitVector evaluatePropositionalFormula(ModelType const& model, s auto checkResult = mc.check(formula); STORM_LOG_THROW(checkResult && checkResult->isExplicitQualitativeCheckResult(), storm::exceptions::UnexpectedException, "Unexpected type of check result for subformula " << formula << "."); - return checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp index 562f4dbfc5..9271fe33e6 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp @@ -51,8 +51,7 @@ std::unique_ptr SparsePcaaAchievabilityQuerycheckAchievability(env); - return std::unique_ptr( - new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp index e4e613f69a..c13762c22e 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp @@ -91,8 +91,7 @@ std::unique_ptr SparsePcaaQuantitativeQuery(new ExplicitQuantitativeCheckResult( this->originalModel.getInitialStates().getNextSetIndex(0), resultForOriginalModel)); } else { - return std::unique_ptr( - new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); } } diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 1a51f2cafc..6eabbd6bda 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -139,9 +139,9 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +151,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +161,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +181,7 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,13 +210,13 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); } } else if (opFormula->isLongRunAverageOperatorFormula()) { - auto lraStates = mc.check(pathFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lraStates = mc.check(pathFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Compute Sat(Forall F (Forall G not "lraStates")) auto forallGloballyNotLraStates = storm::utility::graph::performProb0A(backwardTransitions, ~lraStates, lraStates); absorbingStatesForSubformula = storm::utility::graph::performProb1A(model->getTransitionMatrix(), model->getNondeterministicChoiceIndices(), @@ -432,7 +432,7 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +445,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +455,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +542,7 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp index 81815a9d85..344766e323 100644 --- a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp @@ -176,7 +176,7 @@ std::unique_ptr HybridMdpPrctlModelChecker::checkMultiOb // Convert the explicit result if (explicitResult->isExplicitQualitativeCheckResult()) { - if (explicitResult->template asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { + if (explicitResult->asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { return std::unique_ptr(new storm::modelchecker::SymbolicQualitativeCheckResult( this->getModel().getReachableStates(), this->getModel().getInitialStates(), this->getModel().getManager().getBddOne())); } else { diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 431039c622..1686bbe010 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -92,8 +92,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper step bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -109,7 +109,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -121,8 +121,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -135,7 +135,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet()); @@ -151,7 +151,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -168,7 +168,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -236,7 +236,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -249,7 +249,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.getHint()); @@ -290,7 +290,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); @@ -320,8 +320,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -340,8 +340,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asReachabilityRewardFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 0033abb17f..5930c02fdd 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -139,8 +139,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to have discrete upper time bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -158,7 +158,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -172,8 +172,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -192,7 +192,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -215,7 +215,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -245,7 +245,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -276,14 +276,14 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); if constexpr (std::is_same_v) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { - return storm::modelchecker::computeConditionalProbabilities( - env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, this->getModel().getTransitionMatrix(), - this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, + this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), + leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); } } @@ -363,7 +363,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -383,7 +383,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), @@ -446,7 +446,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); @@ -499,7 +499,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto ret = lexicographic::check(env, this->getModel(), checkTask, formulaChecker); std::unique_ptr result(new LexicographicCheckResult(ret.values, *this->getModel().getInitialStates().begin())); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 02b9e2f177..7bb836cc88 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -133,8 +133,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +155,7 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +426,9 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp index 8fa08b56c7..094a2332cf 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -35,9 +35,9 @@ std::unique_ptr SparsePropositionalModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::BooleanLiteralFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isTrueFormula()) { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); } } @@ -47,7 +47,7 @@ std::unique_ptr SparsePropositionalModelChecker::c storm::logic::AtomicLabelFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(model.hasLabel(stateFormula.getLabel()), storm::exceptions::InvalidPropertyException, "The property refers to unknown label '" << stateFormula.getLabel() << "'."); - return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); } template diff --git a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 506f03b3ff..43296a4d13 100644 --- a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -55,7 +55,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); - storm::storage::BitVector const& psiStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::SparseMatrix const& transitionMatrix = this->getModel().getTransitionMatrix(); uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); @@ -112,7 +112,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -177,7 +177,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -350,8 +350,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Start by determining the states that have a non-zero probability of reaching the target states within the // time bound. @@ -444,7 +444,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); + checkResult->filter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); } return checkResult; } @@ -457,8 +457,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); return computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, checkTask.isOnlyInitialStatesRelevantSet()); @@ -538,7 +538,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker subResultPointer = this->check(eventuallyFormula.getSubformula()); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector const& targetStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); @@ -650,8 +650,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - storm::storage::BitVector phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); // Do some sanity checks to establish some required properties. diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index c43c2cf441..8549ce26d0 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -82,14 +82,12 @@ bool CheckResult::isHybridQuantitativeCheckResult() const { return false; } -template -ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { - return dynamic_cast&>(*this); +ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { + return dynamic_cast(*this); } -template -ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { - return dynamic_cast const&>(*this); +ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { + return dynamic_cast(*this); } template @@ -190,8 +188,6 @@ template QuantitativeCheckResult const& CheckResult::asQuantitativeCheck template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; -template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); -template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; template LexicographicCheckResult& CheckResult::asLexicographicCheckResult(); @@ -225,8 +221,6 @@ template QuantitativeCheckResult const& CheckResult::asQu template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; -template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); -template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; @@ -234,9 +228,6 @@ template QuantitativeCheckResult const& CheckResult::as template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; -template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); -template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; - template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; @@ -244,10 +235,5 @@ template LexicographicCheckResult& CheckResult::asLexicog template LexicographicCheckResult const& CheckResult::asLexicographicCheckResult() const; #endif - -// Instantiation for storm::Interval (carl::Interval) -template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); -template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; - } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/CheckResult.h b/src/storm/modelchecker/results/CheckResult.h index c8ba918329..f46e1abcf9 100644 --- a/src/storm/modelchecker/results/CheckResult.h +++ b/src/storm/modelchecker/results/CheckResult.h @@ -13,7 +13,6 @@ namespace modelchecker { class QualitativeCheckResult; template class QuantitativeCheckResult; -template class ExplicitQualitativeCheckResult; template @@ -78,11 +77,8 @@ class CheckResult { template QuantitativeCheckResult const& asQuantitativeCheckResult() const; - template - ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); - - template - ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; + ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; template ExplicitQuantitativeCheckResult& asExplicitQuantitativeCheckResult(); diff --git a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp index ac58ec1fc2..a9d59197a5 100644 --- a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp @@ -56,8 +56,8 @@ void ExplicitParetoCurveCheckResult::filter(QualitativeCheckResult co STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); - typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 9404a7c355..f608a3065b 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -3,67 +3,53 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/adapters/JsonAdapter.h" -#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/utility/macros.h" namespace storm { namespace modelchecker { - -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { // Intentionally left empty. } -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { // Intentionally left empty. } -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { // Intentionally left empty. } -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { boost::get(truthValues)[state] = value; } -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { // Intentionally left empty. } -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) - : truthValues(std::move(truthValues)) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) : truthValues(std::move(truthValues)) { // Intentionally left empty. } -template -std::unique_ptr ExplicitQualitativeCheckResult::clone() const { - return std::make_unique>(this->truthValues); +std::unique_ptr ExplicitQualitativeCheckResult::clone() const { + return std::make_unique(this->truthValues); } -template -void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, - bool logicalAnd) { +void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, bool logicalAnd) { STORM_LOG_THROW(second.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); STORM_LOG_THROW(first.isResultForAllStates() == second.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); - ExplicitQualitativeCheckResult const& secondCheckResult = static_cast const&>(second); + ExplicitQualitativeCheckResult const& secondCheckResult = static_cast(second); if (first.isResultForAllStates()) { if (logicalAnd) { boost::get(first.truthValues) &= boost::get(secondCheckResult.truthValues); @@ -92,20 +78,17 @@ void ExplicitQualitativeCheckResult::performLogicalOperation(Explicit } } -template -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, true); return *this; } -template -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, false); return *this; } -template -bool ExplicitQualitativeCheckResult::existsTrue() const { +bool ExplicitQualitativeCheckResult::existsTrue() const { if (this->isResultForAllStates()) { return !boost::get(truthValues).empty(); } else { @@ -117,9 +100,7 @@ bool ExplicitQualitativeCheckResult::existsTrue() const { return false; } } - -template -bool ExplicitQualitativeCheckResult::forallTrue() const { +bool ExplicitQualitativeCheckResult::forallTrue() const { if (this->isResultForAllStates()) { return boost::get(truthValues).full(); } else { @@ -132,8 +113,7 @@ bool ExplicitQualitativeCheckResult::forallTrue() const { } } -template -uint64_t ExplicitQualitativeCheckResult::count() const { +uint64_t ExplicitQualitativeCheckResult::count() const { if (this->isResultForAllStates()) { return boost::get(truthValues).getNumberOfSetBits(); } else { @@ -147,8 +127,7 @@ uint64_t ExplicitQualitativeCheckResult::count() const { } } -template -bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { +bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { if (this->isResultForAllStates()) { return boost::get(truthValues).get(state); } else { @@ -159,18 +138,15 @@ bool ExplicitQualitativeCheckResult::operator[](storm::storage::spars } } -template -typename ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { +ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { return boost::get(truthValues); } -template -typename ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { +ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { return boost::get(truthValues); } -template -void ExplicitQualitativeCheckResult::complement() { +void ExplicitQualitativeCheckResult::complement() { if (this->isResultForAllStates()) { boost::get(truthValues).complement(); } else { @@ -180,23 +156,19 @@ void ExplicitQualitativeCheckResult::complement() { } } -template -bool ExplicitQualitativeCheckResult::isExplicit() const { +bool ExplicitQualitativeCheckResult::isExplicit() const { return true; } -template -bool ExplicitQualitativeCheckResult::isResultForAllStates() const { +bool ExplicitQualitativeCheckResult::isResultForAllStates() const { return truthValues.which() == 0; } -template -bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { +bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { return true; } -template -std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { +std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { if (this->isResultForAllStates()) { vector_type const& vector = boost::get(truthValues); bool allTrue = vector.full(); @@ -239,12 +211,11 @@ std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostr return out; } -template -void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { +void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { @@ -288,10 +259,9 @@ void insertJsonEntry(storm::json& json, uint64_t const& id, bo json.push_back(std::move(entry)); } -template template -storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, - std::optional const& stateLabels) const { +storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, + std::optional const& stateLabels) const { storm::json result; if (this->isResultForAllStates()) { vector_type const& valuesAsVector = boost::get(truthValues); @@ -307,33 +277,10 @@ storm::json ExplicitQualitativeCheckResult::toJson( return result; } -// Explicit template instantiations -template class ExplicitQualitativeCheckResult; -template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, - std::optional const&) const; - -#ifdef STORM_HAVE_CARL -template storm::json ExplicitQualitativeCheckResult::toJson( - std::optional const&, std::optional const&) const; - -template class ExplicitQualitativeCheckResult; -template storm::json ExplicitQualitativeCheckResult::toJson( - std::optional const&, std::optional const&) const; -template storm::json ExplicitQualitativeCheckResult::toJson( - std::optional const&, std::optional const&) const; - -template class ExplicitQualitativeCheckResult; -template storm::json ExplicitQualitativeCheckResult::toJson( - std::optional const&, std::optional const&) const; -template storm::json ExplicitQualitativeCheckResult::toJson( - std::optional const&, std::optional const&) const; - -template class ExplicitQualitativeCheckResult; -template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, - std::optional const&) const; -template storm::json ExplicitQualitativeCheckResult::toJson( +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; -#endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 9e67d1b277..8e13acbef7 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -9,15 +9,12 @@ #include "storm/modelchecker/results/QualitativeCheckResult.h" #include "storm/models/sparse/StateLabeling.h" #include "storm/storage/BitVector.h" -#include "storm/storage/Scheduler.h" #include "storm/storage/sparse/StateType.h" #include "storm/storage/sparse/StateValuations.h" namespace storm { namespace modelchecker { - -template class ExplicitQualitativeCheckResult : public QualitativeCheckResult { public: typedef storm::storage::BitVector vector_type; @@ -72,9 +69,6 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { // The values of the quantitative check result. boost::variant truthValues; - - // An optional scheduler that accompanies the values. - boost::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 278ef000b4..3464ee9381 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -61,7 +61,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boos } template -ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { +ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { if (other.isResultForAllStates()) { storm::storage::BitVector const& bvValues = other.getTruthValuesVector(); @@ -73,7 +73,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(Expl values = newVector; } else { - typename ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); + ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); map_type newMap; for (auto const& e : bitMap) { @@ -109,8 +109,8 @@ void ExplicitQuantitativeCheckResult::filter(QualitativeCheckResult c STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); - typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { map_type newMap; @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } } diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index 125752ca14..e9c9ac487d 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -16,7 +16,6 @@ namespace storm { namespace modelchecker { // Forward declaration -template class ExplicitQualitativeCheckResult; template @@ -40,7 +39,7 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult const& other); + explicit ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other); virtual ~ExplicitQuantitativeCheckResult() = default; diff --git a/src/storm/modelchecker/results/LexicographicCheckResult.cpp b/src/storm/modelchecker/results/LexicographicCheckResult.cpp index 0206554088..027f21f3ef 100644 --- a/src/storm/modelchecker/results/LexicographicCheckResult.cpp +++ b/src/storm/modelchecker/results/LexicographicCheckResult.cpp @@ -43,8 +43,8 @@ void LexicographicCheckResult::filter(QualitativeCheckResult const& f STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); - typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp index 2f3206ac29..4828c13ef7 100644 --- a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp +++ b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp @@ -160,8 +160,8 @@ void BisimulationDecomposition::Options::checkAndSetMe storm::modelchecker::SparsePropositionalModelChecker checker(model); std::unique_ptr phiStatesCheckResult = checker.check(*leftSubformula); std::unique_ptr psiStatesCheckResult = checker.check(*rightSubformula); - phiStates = phiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - psiStates = psiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + phiStates = phiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = psiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { optimalityType = boost::none; } diff --git a/src/storm/transformer/MemoryIncorporation.cpp b/src/storm/transformer/MemoryIncorporation.cpp index 14554ec711..a0d894e6a3 100644 --- a/src/storm/transformer/MemoryIncorporation.cpp +++ b/src/storm/transformer/MemoryIncorporation.cpp @@ -27,8 +27,7 @@ storm::storage::MemoryStructure getGoalMemory(SparseModelType const& model, stor "The subformula " << propositionalGoalStateFormula << " should be propositional."); storm::modelchecker::SparsePropositionalModelChecker mc(model); - storm::storage::BitVector goalStates = - mc.check(propositionalGoalStateFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = mc.check(propositionalGoalStateFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied for all initial states. In such a case the trivial memory structure suffices. if (model.getInitialStates().isSubsetOf(goalStates)) { diff --git a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp index 03e4fb5f67..ed641deee7 100644 --- a/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/analysis/MonotonicityCheckerTest.cpp @@ -55,7 +55,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -103,7 +103,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -152,7 +152,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -205,7 +205,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -259,7 +259,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/analysis/OrderExtenderTest.cpp b/src/test/storm-pars/analysis/OrderExtenderTest.cpp index 13c98eda25..f201d0276b 100644 --- a/src/test/storm-pars/analysis/OrderExtenderTest.cpp +++ b/src/test/storm-pars/analysis/OrderExtenderTest.cpp @@ -146,7 +146,7 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -193,7 +193,7 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -270,7 +270,7 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -361,7 +361,7 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -414,7 +414,7 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp index 05d8bb66fc..4f3d460275 100644 --- a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp @@ -54,7 +54,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -62,7 +62,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); } diff --git a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp index 46362ad298..a0cafe14c3 100644 --- a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp @@ -49,7 +49,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -57,7 +57,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); diff --git a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp index f65a91c100..b205fbc634 100644 --- a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp @@ -294,7 +294,7 @@ class CtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique>(model->template as()->getInitialStates()); + return std::make_unique(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp index 619f0d0ef5..ea1f9c0056 100644 --- a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp @@ -364,7 +364,7 @@ class LraCtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique>(model->template as()->getInitialStates()); + return std::make_unique(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp index b58391fc9e..4220981ab1 100644 --- a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp @@ -235,7 +235,7 @@ class MarkovAutomatonCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique>(model->template as()->getInitialStates()); + return std::make_unique(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp index 42fd7aa01e..755a60f403 100644 --- a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp @@ -274,13 +274,13 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { @@ -293,7 +293,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } @@ -359,7 +359,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } ++formulaIndex; @@ -371,7 +371,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp index 2fe681ff98..03e6762797 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp @@ -44,9 +44,9 @@ TEST_F(SparseMaCbMultiObjectiveModelCheckerTest, server) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp index bda5ce430b..ee24093d2b 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp @@ -175,12 +175,12 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_achievability_3Obj std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) { @@ -213,7 +213,7 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_pareto_2Obj) { diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp index 4eae82674a..306364575c 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp @@ -45,11 +45,11 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); } TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { @@ -71,7 +71,7 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); } /* This test takes a little bit too long ... @@ -90,6 +90,6 @@ formulas)->as>(); uint_fast64_ std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(*mdp, formulas[0]->asMultiObjectiveFormula()) ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); } */ diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp index d955034649..f92a5d9f1d 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp @@ -231,11 +231,11 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, zeroconf) { @@ -307,7 +307,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, tiny_rewards_negative) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { @@ -331,7 +331,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, dpm) { diff --git a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp index ec626279fb..cb3785ac62 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp @@ -585,7 +585,7 @@ class DtmcPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique>(model->template as()->getInitialStates()); + return std::make_unique(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp index 0b8b8f47de..23cb02ea19 100644 --- a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp @@ -591,7 +591,7 @@ class MdpPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique>(model->template as()->getInitialStates()); + return std::make_unique(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp index a006e5edcb..b4d82e499f 100644 --- a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp @@ -167,7 +167,7 @@ class QuantileQueryTest : public ::testing::Test { std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) const { - return std::make_unique>(model->getInitialStates()); + return std::make_unique(model->getInitialStates()); } }; diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 3d509f2fbc..27a9254a16 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -17,11 +17,11 @@ std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique>(model->getInitialStates()); + return std::make_unique(model->getInitialStates()); } std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) { - return std::make_unique>(model->getInitialStates()); + return std::make_unique(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, From 8d74335cb7518561690b8124b5a1e93018df55cb Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 28 Nov 2025 13:58:14 +0100 Subject: [PATCH 067/102] wip --- resources/scripts/auto-format.sh | 4 +-- .../helper/conditional/ConditionalHelper.cpp | 32 +++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/resources/scripts/auto-format.sh b/resources/scripts/auto-format.sh index 3ac97c41af..ba7cf542b8 100755 --- a/resources/scripts/auto-format.sh +++ b/resources/scripts/auto-format.sh @@ -16,7 +16,7 @@ do exit 1 fi done -if ! command -v clang-format &> /dev/null +if ! command -v clang-format-20 &> /dev/null then echo "Unable to find clang-format executable. Is it installed?" exit 1 @@ -49,4 +49,4 @@ auto_format_find_expression+=" -false ) ) -print" set -f # find files and invoke clang-format with in-place option -find $auto_format_find_expression | xargs clang-format -i -style=file +find $auto_format_find_expression | xargs clang-format-20 -i -style=file diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 814d893989..5d1a1de32a 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -135,23 +135,27 @@ typename internal::SolverResult solveMinMaxEquationSystem(storm::Envi * @note This code is optimized for cases where not all states are reachable from the initial states. */ template -void computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, - storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { +std::unique_ptr> computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, + storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::BitVector const& initialStates, + storm::storage::BitVector const& allowedStates, + storm::storage::BitVector const& targetStates) { if (initialStates.empty()) { // nothing to do - return; + return nullptr; } auto const reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, allowedStates, targetStates); auto const subTargets = targetStates % reachableStates; // Catch the case where no target is reachable from an initial state. In this case, there is nothing to do since all probabilities are zero. if (subTargets.empty()) { - return; + return nullptr; } auto const subInits = initialStates % reachableStates; auto const submatrix = transitionMatrix.getSubmatrix(true, reachableStates, reachableStates); auto const subResult = helper::SparseMdpPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(dir, subInits), submatrix, submatrix.transpose(true), storm::storage::BitVector(subTargets.size(), true), subTargets, false, true); + auto origInitIt = initialStates.begin(); for (auto subInit : subInits) { auto const& val = subResult.values[subInit]; @@ -160,6 +164,15 @@ void computeReachabilityProbabilities(Environment const& env, std::map scheduler(transitionMatrix.getRowGroupCount()); + auto submatrixIdx = 0; + for (auto state : reachableStates) { + scheduler.setChoice(subResult.scheduler->getChoice(submatrixIdx), state); + ++submatrixIdx; + } + + return std::make_unique>(std::move(scheduler)); } /*! @@ -267,11 +280,12 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, targetStates); auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates); + // compute schedulers for reaching target and condition states from target and condition states std::vector schedulerChoicesForReachingTargetStates; std::vector schedulerChoicesForReachingConditionStates; - auto schedulerForTargetStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, - allStates, extendedTargetStates); + auto schedulerForTargetStates = + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); schedulerChoicesForReachingTargetStates = std::vector(transitionMatrix.getRowGroupCount(), 0); if (schedulerForTargetStates) { for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { @@ -279,8 +293,8 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver } } - auto schedulerForConditionStates = computeReachabilityProbabilitiesAndScheduler(env, nonZeroTargetStateValues, dir, transitionMatrix, - targetAndNotCondFailStates, allStates, extendedConditionStates); + auto schedulerForConditionStates = + computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); schedulerChoicesForReachingConditionStates = std::vector(transitionMatrix.getRowGroupCount(), 0); if (schedulerForConditionStates) { for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { From 7b58f5568b819b702d8145f66ceb013d46eebc4c Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 1 Dec 2025 14:32:23 +0100 Subject: [PATCH 068/102] More --- .../helper/conditional/ConditionalHelper.cpp | 51 ++++++++----------- .../IterativeMinMaxLinearEquationSolver.cpp | 2 +- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 5d1a1de32a..910f2ec669 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -141,14 +141,16 @@ std::unique_ptr> computeReachabilityProbabi storm::storage::BitVector const& initialStates, storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { + storm::storage::Scheduler scheduler(transitionMatrix.getRowGroupCount()); + if (initialStates.empty()) { // nothing to do - return nullptr; + return std::make_unique>(std::move(scheduler)); } auto const reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, allowedStates, targetStates); auto const subTargets = targetStates % reachableStates; // Catch the case where no target is reachable from an initial state. In this case, there is nothing to do since all probabilities are zero. if (subTargets.empty()) { - return nullptr; + return std::make_unique>(std::move(scheduler)); } auto const subInits = initialStates % reachableStates; auto const submatrix = transitionMatrix.getSubmatrix(true, reachableStates, reachableStates); @@ -165,7 +167,6 @@ std::unique_ptr> computeReachabilityProbabi ++origInitIt; } - storm::storage::Scheduler scheduler(transitionMatrix.getRowGroupCount()); auto submatrixIdx = 0; for (auto state : reachableStates) { scheduler.setChoice(subResult.scheduler->getChoice(submatrixIdx), state); @@ -247,9 +248,9 @@ struct NormalFormData { // TerminalStates is a superset of conditionStates and dom(nonZeroTargetStateValues). // For a terminalState that is not a conditionState, it is impossible to (reach the condition and not reach the target). - std::vector const + std::unique_ptr> schedulerChoicesForReachingTargetStates; // Scheduler choices for reaching target states, used for constructing the resulting scheduler - std::vector const + std::unique_ptr> schedulerChoicesForReachingConditionStates; // Scheduler choices for reaching condition states, used for constructing the resulting scheduler ValueType getTargetValue(uint64_t state) const { @@ -281,26 +282,10 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates); // compute schedulers for reaching target and condition states from target and condition states - std::vector schedulerChoicesForReachingTargetStates; - std::vector schedulerChoicesForReachingConditionStates; - - auto schedulerForTargetStates = + std::unique_ptr> schedulerChoicesForReachingTargetStates = computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); - schedulerChoicesForReachingTargetStates = std::vector(transitionMatrix.getRowGroupCount(), 0); - if (schedulerForTargetStates) { - for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { - schedulerChoicesForReachingTargetStates[state] = schedulerForTargetStates->getChoice(state).getDeterministicChoice(); - } - } - - auto schedulerForConditionStates = + std::unique_ptr> schedulerChoicesForReachingConditionStates = computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); - schedulerChoicesForReachingConditionStates = std::vector(transitionMatrix.getRowGroupCount(), 0); - if (schedulerForConditionStates) { - for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { - schedulerChoicesForReachingConditionStates[state] = schedulerForConditionStates->getChoice(state).getDeterministicChoice(); - } - } // get states where the optimal policy reaches the condition with positive probability auto terminalStatesThatReachCondition = extendedConditionStates; @@ -976,8 +961,8 @@ typename internal::ResultReturnType computeViaBisection(Environment c "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); SolutionType const precision = [&env, boundOption]() { if (storm::NumberTraits::IsExact || env.solver().isForceExact()) { - STORM_LOG_WARN_COND(storm::NumberTraits::IsExact && boundOption == BisectionMethodBounds::Advanced, - "Selected bisection method with exact precision in a setting that might not terminate."); + // STORM_LOG_WARN_COND(storm::NumberTraits::IsExact && boundOption == BisectionMethodBounds::Advanced, + // "Selected bisection method with exact precision in a setting that might not terminate."); return storm::utility::zero(); } else { return storm::utility::convertNumber(env.solver().minMax().getPrecision()); @@ -1350,17 +1335,25 @@ std::unique_ptr computeConditionalProbabilities(Environment const& for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { // set choices for memory 0 if (conditionStates.get(state)) { - finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates[state], state, 0); + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates->getChoice(state), state, 0); } else if (targetStates.get(state)) { - finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates[state], state, 0); + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates->getChoice(state), state, 0); } else { finalScheduler->setChoice(scheduler->getChoice(state), state, 0); } // set choices for memory 1, these are the choices after condition was reached - finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates[state], state, 1); + if (normalFormData.schedulerChoicesForReachingTargetStates->isChoiceSelected(state)) { + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates->getChoice(state), state, 1); + } else { + finalScheduler->setChoice(0, state, 1); // arbitrary choice if no choice was recorded, TODO: this could be problematic for paynt? + } // set choices for memory 2, these are the choices after target was reached - finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates[state], state, 2); + if (normalFormData.schedulerChoicesForReachingConditionStates->isChoiceSelected(state)) { + finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates->getChoice(state), state, 2); + } else { + finalScheduler->setChoice(0, state, 2); // arbitrary choice if no choice was recorded, TODO: this could be problematic for paynt? + } } result->asExplicitQuantitativeCheckResult().setScheduler(std::move(finalScheduler)); diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp index 4dd35b55b2..77a9ff6888 100644 --- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp @@ -63,7 +63,7 @@ MinMaxMethod IterativeMinMaxLinearEquationSolver::getMe "different method."); method = MinMaxMethod::PolicyIteration; } else { - STORM_LOG_WARN("The selected solution method " << toString(method) << " does not guarantee exact results."); + // STORM_LOG_WARN("The selected solution method " << toString(method) << " does not guarantee exact results."); } } else if (env.solver().isForceSoundness() && method != MinMaxMethod::SoundValueIteration && method != MinMaxMethod::IntervalIteration && method != MinMaxMethod::PolicyIteration && method != MinMaxMethod::RationalSearch && method != MinMaxMethod::OptimisticValueIteration && From 96b59894f5499fcebb3d47873510a2eda07acf82 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 2 Dec 2025 10:37:02 +0100 Subject: [PATCH 069/102] don't make scheduler when not requested --- .../helper/conditional/ConditionalHelper.cpp | 179 ++++++++---------- 1 file changed, 83 insertions(+), 96 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 910f2ec669..be411d567b 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -107,7 +107,8 @@ struct SolverResult { template typename internal::SolverResult solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, - storm::solver::OptimizationDirection const dir, uint64_t const initialState) { + storm::solver::OptimizationDirection const dir, uint64_t const initialState, + bool computeScheduler) { // Initialize the solution vector. std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); @@ -119,13 +120,15 @@ typename internal::SolverResult solveMinMaxEquationSystem(storm::Envi solver->setHasNoEndComponents(true); solver->setLowerBound(storm::utility::zero()); solver->setUpperBound(storm::utility::one()); - solver->setTrackScheduler(true); + solver->setTrackScheduler(computeScheduler); // Solve the corresponding system of equations. solver->solveEquations(env, x, rowValues); SolverResult result(x[initialState]); - result.scheduler = std::move(solver->getSchedulerChoices()); + if (computeScheduler) { + result.scheduler = std::move(solver->getSchedulerChoices()); + } return result; } @@ -135,12 +138,10 @@ typename internal::SolverResult solveMinMaxEquationSystem(storm::Envi * @note This code is optimized for cases where not all states are reachable from the initial states. */ template -std::unique_ptr> computeReachabilityProbabilities(Environment const& env, std::map& nonZeroResults, - storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::BitVector const& initialStates, - storm::storage::BitVector const& allowedStates, - storm::storage::BitVector const& targetStates) { +std::unique_ptr> computeReachabilityProbabilities( + Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, + storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates, bool computeScheduler = true) { storm::storage::Scheduler scheduler(transitionMatrix.getRowGroupCount()); if (initialStates.empty()) { // nothing to do @@ -167,6 +168,10 @@ std::unique_ptr> computeReachabilityProbabi ++origInitIt; } + if (!computeScheduler) { + return nullptr; + } + auto submatrixIdx = 0; for (auto state : reachableStates) { scheduler.setChoice(subResult.scheduler->getChoice(submatrixIdx), state); @@ -176,32 +181,6 @@ std::unique_ptr> computeReachabilityProbabi return std::make_unique>(std::move(scheduler)); } -/*! - * Computes the reachability probabilities for the given target states and inserts all non-zero values into the given map. - * TODO we can optimize this by only considering reachable states as well but I don't have the strength to do it now - */ -template -std::unique_ptr> computeReachabilityProbabilitiesAndScheduler( - Environment const& env, std::map& nonZeroResults, storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, - storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates) { - if (initialStates.empty()) { // nothing to do - return nullptr; - } - - auto result = helper::SparseMdpPrctlHelper::computeUntilProbabilities( - env, storm::solver::SolveGoal(dir, initialStates), transitionMatrix, transitionMatrix.transpose(true), - storm::storage::BitVector(targetStates.size(), true), targetStates, false, true); - for (auto initState : initialStates) { - auto const& val = result.values[initState]; - if (!storm::utility::isZero(val)) { - nonZeroResults.emplace(initState, val); - } - } - - return std::move(result.scheduler); -} - /*! * Uses the precomputed the reachability probabilities for the given target states and inserts all non-zero values into the given map. * @note This code is optimized for cases where not all states are reachable from the initial states. @@ -268,7 +247,7 @@ struct NormalFormData { }; template -NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, +NormalFormData obtainNormalForm(Environment const& env, storm::solver::OptimizationDirection const dir, bool computeScheduler, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& relevantStates, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { @@ -282,10 +261,10 @@ NormalFormData obtainNormalForm(Environment const& env, storm::solver auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates); // compute schedulers for reaching target and condition states from target and condition states - std::unique_ptr> schedulerChoicesForReachingTargetStates = - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates); - std::unique_ptr> schedulerChoicesForReachingConditionStates = - computeReachabilityProbabilities(env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates); + std::unique_ptr> schedulerChoicesForReachingTargetStates = computeReachabilityProbabilities( + env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates, computeScheduler); + std::unique_ptr> schedulerChoicesForReachingConditionStates = computeReachabilityProbabilities( + env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates, computeScheduler); // get states where the optimal policy reaches the condition with positive probability auto terminalStatesThatReachCondition = extendedConditionStates; @@ -500,7 +479,7 @@ struct ResultReturnType { */ template typename internal::ResultReturnType computeViaRestartMethod(Environment const& env, uint64_t const initialState, - storm::solver::OptimizationDirection const dir, + storm::solver::OptimizationDirection const dir, bool computeScheduler, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { @@ -580,7 +559,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme STORM_LOG_INFO("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " << matrix.getEntryCount() << " transitions."); // Finally, solve the equation system - auto result = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix); + auto result = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix, computeScheduler); storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); storm::storage::BitVector initialComponentExitStates(transitionMatrix.getRowGroupCount(), false); @@ -615,14 +594,17 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme initialComponentExitStates.set(originalState, true); } - // std::vector finalSchedulerChoices(transitionMatrix.getRowGroupCount(), -1); - storm::storage::BitVector maybeStatesWithChoice(maybeStates.size(), false); - std::unique_ptr> scheduler; - uint64_t chosenInitialComponentExitState; - uint64_t chosenInitialComponentExit; - scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); - // std::vector ecsToExits(matrix.getRowGroupCount(), 0); - if (result.hasScheduler()) { + // Create result without scheduler + auto finalResult = ResultReturnType(result.initialStateValue); + + // If requested, construct the scheduler for the original model + if (computeScheduler && result.hasScheduler()) { + storm::storage::BitVector maybeStatesWithChoice(maybeStates.size(), false); + std::unique_ptr> scheduler; + uint64_t chosenInitialComponentExitState; + uint64_t chosenInitialComponentExit; + scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + uint64_t state = 0; for (auto& choice : *result.scheduler) { uint64_t firstRowIndex = matrix.getRowGroupIndices()[state]; @@ -650,34 +632,32 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme } originalState = index; - // finalSchedulerChoices[originalState] = originalChoice; scheduler->setChoice(originalChoice, originalState); maybeStatesWithChoice.set(originalState, true); - // ecsToExits[state] = originalState; if (state == initStateInMatrix) { chosenInitialComponentExitState = originalState; chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState] + originalChoice; } ++state; } - } - std::vector stateToFinalEc(transitionMatrix.getRowGroupCount(), std::numeric_limits::max()); - uint64_t state = 0; - for (auto s : maybeStates) { - auto mappedState = state; - mappedState = ecElimResult1.has_value() ? ecElimResult1->oldToNewStateMapping[mappedState] : mappedState; - mappedState = ecElimResult2.has_value() ? ecElimResult2->oldToNewStateMapping[mappedState] : mappedState; - stateToFinalEc[s] = mappedState; - state++; - } + std::vector stateToFinalEc(transitionMatrix.getRowGroupCount(), std::numeric_limits::max()); + state = 0; + for (auto s : maybeStates) { + auto mappedState = state; + mappedState = ecElimResult1.has_value() ? ecElimResult1->oldToNewStateMapping[mappedState] : mappedState; + mappedState = ecElimResult2.has_value() ? ecElimResult2->oldToNewStateMapping[mappedState] : mappedState; + stateToFinalEc[s] = mappedState; + state++; + } - auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, - stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitStates, initialComponentExitRows, - chosenInitialComponentExitState, chosenInitialComponentExit); + auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, + stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitStates, initialComponentExitRows, + chosenInitialComponentExitState, chosenInitialComponentExit); - auto finalResult = ResultReturnType(result.initialStateValue, std::move(scheduler)); + finalResult.scheduler = std::move(scheduler); + } return finalResult; } @@ -836,7 +816,7 @@ class WeightedReachabilityHelper { } internal::SolverResult computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, - ValueType const& conditionWeight) const { + ValueType const& conditionWeight, bool computeScheduler) const { auto rowValues = createScaledVector(targetWeight, targetRowValues, conditionWeight, conditionRowValues); // Initialize the solution vector. @@ -850,13 +830,15 @@ class WeightedReachabilityHelper { solver->setHasNoEndComponents(true); solver->setLowerBound(-storm::utility::one()); solver->setUpperBound(storm::utility::one()); - solver->setTrackScheduler(true); + solver->setTrackScheduler(computeScheduler); // Solve the corresponding system of equations. solver->solveEquations(env, x, rowValues); SolverResult result(x[initialStateInSubmatrix]); - result.scheduler = std::move(solver->getSchedulerChoices()); + if (computeScheduler) { + result.scheduler = std::move(solver->getSchedulerChoices()); + } return result; } @@ -952,7 +934,7 @@ class WeightedReachabilityHelper { enum class BisectionMethodBounds { Simple, Advanced }; template typename internal::ResultReturnType computeViaBisection(Environment const& env, BisectionMethodBounds boundOption, uint64_t const initialState, - storm::solver::SolveGoal goal, + storm::solver::SolveGoal goal, bool computeScheduler, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { @@ -975,10 +957,10 @@ typename internal::ResultReturnType computeViaBisection(Environment c SolutionType pMax{storm::utility::one()}; if (boundOption == BisectionMethodBounds::Advanced) { - auto pMinRes = - wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); - auto pMaxRes = - wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); + auto pMinRes = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one(), + computeScheduler); + auto pMaxRes = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one(), + computeScheduler); pMin = pMinRes.initialStateValue; pMax = pMaxRes.initialStateValue; STORM_LOG_TRACE("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) @@ -995,7 +977,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c SolverResult res(0); for (uint64_t iterationCount = 1; true; ++iterationCount) { // evaluate the current middle - res = wrh.computeWeightedDiff(env, goal.direction(), storm::utility::one(), -middle); + res = wrh.computeWeightedDiff(env, goal.direction(), storm::utility::one(), -middle, computeScheduler); SolutionType const middleValue = res.initialStateValue; // update the bounds and new middle value according to the bisection method if (boundOption == BisectionMethodBounds::Simple) { @@ -1083,12 +1065,17 @@ typename internal::ResultReturnType computeViaBisection(Environment c } } - storm::storage::BitVector maybeStatesWithChoice(normalForm.maybeStates.size(), false); - std::unique_ptr> scheduler; - uint64_t chosenInitialComponentExitState; - uint64_t chosenInitialComponentExit; - scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); - if (res.hasScheduler()) { + // Create result without scheduler + auto finalResult = ResultReturnType((*lowerBound + *upperBound) / 2); + + // If requested, construct the scheduler for the original model + if (computeScheduler && res.hasScheduler()) { + storm::storage::BitVector maybeStatesWithChoice(normalForm.maybeStates.size(), false); + std::unique_ptr> scheduler; + uint64_t chosenInitialComponentExitState; + uint64_t chosenInitialComponentExit; + scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + uint64_t state = 0; for (auto& choice : *res.scheduler) { uint64_t originalChoice; @@ -1121,14 +1108,14 @@ typename internal::ResultReturnType computeViaBisection(Environment c ++state; } - } - auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, - wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitStates, wrh.initialComponentExitRows, - chosenInitialComponentExitState, chosenInitialComponentExit); + auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, + maybeStatesWithChoice, wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitStates, + wrh.initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); - auto finalResult = ResultReturnType((*lowerBound + *upperBound) / 2, std::move(scheduler)); + finalResult.scheduler = std::move(scheduler); + } return finalResult; } @@ -1219,8 +1206,8 @@ std::unique_ptr computeConditionalProbabilities(Environment const& STORM_LOG_TRACE("Computing conditional probabilities for a model with " << transitionMatrix.getRowGroupCount() << " states and " << transitionMatrix.getEntryCount() << " transitions."); // storm::utility::Stopwatch sw(true); - auto normalFormData = internal::obtainNormalForm(normalFormConstructionEnv, goal.direction(), transitionMatrix, backwardTransitions, goal.relevantValues(), - targetStates, conditionStates); + auto normalFormData = internal::obtainNormalForm(normalFormConstructionEnv, goal.direction(), checkTask.isProduceSchedulersSet(), transitionMatrix, + backwardTransitions, goal.relevantValues(), targetStates, conditionStates); // sw.stop(); // STORM_PRINT_AND_LOG("Time for obtaining the normal form: " << sw << ".\n"); // Then, we solve the induced problem using the selected algorithm @@ -1241,22 +1228,22 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // sw.restart(); switch (alg) { case ConditionalAlgorithmSetting::Restart: { - auto result = - internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, backwardTransitions, normalFormData); + auto result = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), checkTask.isProduceSchedulersSet(), + transitionMatrix, backwardTransitions, normalFormData); initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; } case ConditionalAlgorithmSetting::Bisection: { - auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal, transitionMatrix, - backwardTransitions, normalFormData); + auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal, + checkTask.isProduceSchedulersSet(), transitionMatrix, backwardTransitions, normalFormData); initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; } case ConditionalAlgorithmSetting::BisectionAdvanced: { - auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal, transitionMatrix, - backwardTransitions, normalFormData); + auto result = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal, + checkTask.isProduceSchedulersSet(), transitionMatrix, backwardTransitions, normalFormData); initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; From 83d4b5000cd96ea378dedfd60a28047f03948a4a Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:33:30 +0100 Subject: [PATCH 070/102] Add ValueType to ExplicitQualitativeCheckResult --- src/storm-cli-utilities/model-handling.h | 20 +-- .../api/counterexamples.cpp | 2 +- .../MILPMinimalLabelSetGenerator.h | 6 +- .../SMTMinimalLabelSetGenerator.h | 6 +- .../modelchecker/DFTModelChecker.cpp | 2 +- src/storm-pars-cli/sampling.h | 2 +- src/storm-pars-cli/solutionFunctions.h | 2 +- ...rseDerivativeInstantiationModelChecker.cpp | 8 +- .../SparseDtmcInstantiationModelChecker.cpp | 2 +- .../SparseMdpInstantiationModelChecker.cpp | 2 +- ...SparseDtmcParameterLiftingModelChecker.cpp | 10 +- .../SparseMdpParameterLiftingModelChecker.cpp | 10 +- .../SparseParameterLiftingModelChecker.cpp | 15 +-- ...tingSparseParameterLiftingModelChecker.cpp | 10 +- .../region/monotonicity/OrderExtender.cpp | 6 +- .../SparseParametricDtmcSimplifier.cpp | 10 +- .../SparseParametricMdpSimplifier.cpp | 10 +- .../analysis/PermissiveSchedulers.cpp | 10 +- src/storm-pomdp-cli/storm-pomdp.cpp | 2 +- .../analysis/FormulaInformation.cpp | 2 +- .../analysis/QualitativeAnalysisOnGraphs.cpp | 2 +- .../GlobalPomdpMecChoiceEliminator.cpp | 2 +- src/storm/api/export.h | 3 +- .../modelchecker/AbstractModelChecker.cpp | 2 +- .../csl/SparseCtmcCslModelChecker.cpp | 26 ++-- .../SparseMarkovAutomatonCslModelChecker.cpp | 22 ++-- .../SparseCbAchievabilityQuery.cpp | 2 +- ...eterministicSchedsAchievabilityChecker.cpp | 4 +- .../DeterministicSchedsObjectiveHelper.cpp | 2 +- .../pcaa/SparsePcaaAchievabilityQuery.cpp | 3 +- .../pcaa/SparsePcaaQuantitativeQuery.cpp | 3 +- .../SparseMultiObjectivePreprocessor.cpp | 30 ++--- .../prctl/HybridMdpPrctlModelChecker.cpp | 2 +- .../prctl/SparseDtmcPrctlModelChecker.cpp | 30 ++--- .../prctl/SparseMdpPrctlModelChecker.cpp | 28 ++--- .../helper/rewardbounded/ProductModel.cpp | 10 +- .../SparsePropositionalModelChecker.cpp | 6 +- .../SparseDtmcEliminationModelChecker.cpp | 22 ++-- .../modelchecker/results/CheckResult.cpp | 22 +++- src/storm/modelchecker/results/CheckResult.h | 8 +- .../ExplicitParetoCurveCheckResult.cpp | 4 +- .../ExplicitQualitativeCheckResult.cpp | 117 +++++++++++++----- .../results/ExplicitQualitativeCheckResult.h | 6 + .../ExplicitQuantitativeCheckResult.cpp | 12 +- .../results/ExplicitQuantitativeCheckResult.h | 3 +- .../results/LexicographicCheckResult.cpp | 4 +- .../BisimulationDecomposition.cpp | 4 +- src/storm/transformer/MemoryIncorporation.cpp | 3 +- .../monotonicity/MonotonicityCheckerTest.cpp | 10 +- .../region/monotonicity/OrderExtenderTest.cpp | 10 +- .../analysis/MilpPermissiveSchedulerTest.cpp | 4 +- .../analysis/SmtPermissiveSchedulerTest.cpp | 4 +- .../csl/CtmcCslModelCheckerTest.cpp | 2 +- .../csl/LraCtmcCslModelCheckerTest.cpp | 2 +- .../MarkovAutomatonCslModelCheckerTest.cpp | 2 +- ...ultiObjectiveSchedRestModelCheckerTest.cpp | 10 +- ...arseMaCbMultiObjectiveModelCheckerTest.cpp | 4 +- ...seMaPcaaMultiObjectiveModelCheckerTest.cpp | 6 +- ...rseMdpCbMultiObjectiveModelCheckerTest.cpp | 8 +- ...eMdpPcaaMultiObjectiveModelCheckerTest.cpp | 8 +- .../prctl/dtmc/DtmcPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/MdpPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/QuantileQueryTest.cpp | 2 +- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 4 +- 64 files changed, 343 insertions(+), 256 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 8dcd741e1b..6f7eaee4b2 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -903,14 +903,14 @@ inline void printCounterexample(std::shared_ptr - requires(!std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { +requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, + SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template - requires(std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { +requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, + SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -966,8 +966,8 @@ inline void generateCounterexamples(std::shared_ptr const& sparseMode } template - requires(!storm::IsIntervalType) -void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { +requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, + storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1034,9 +1034,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template - requires(!storm::IsIntervalType) -void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { +requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, + storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; @@ -1302,7 +1302,7 @@ void verifyModel(std::shared_ptr> const& std::unique_ptr filter; if (filterForInitialStates) { - filter = std::make_unique(sparseModel->getInitialStates()); + filter = std::make_unique>(sparseModel->getInitialStates()); } else if (!states->isTrueFormula()) { // No need to apply filter if it is the formula 'true' filter = storm::api::verifyWithSparseEngine(mpi.env, sparseModel, storm::api::createTask(states, false)); } diff --git a/src/storm-counterexamples/api/counterexamples.cpp b/src/storm-counterexamples/api/counterexamples.cpp index 6738bf2239..af0104a901 100644 --- a/src/storm-counterexamples/api/counterexamples.cpp +++ b/src/storm-counterexamples/api/counterexamples.cpp @@ -45,7 +45,7 @@ std::shared_ptr computeKShortestPathCoun storm::logic::EventuallyFormula const& eventuallyFormula = subformula.asEventuallyFormula(); std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); // Check if counterexample is even possible storm::storage::BitVector phiStates(model->getNumberOfStates(), true); diff --git a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h index cdd057d069..e14a490411 100644 --- a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h @@ -1023,8 +1023,8 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); phiStates = leftQualitativeResult.getTruthValuesVector(); psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -1033,7 +1033,7 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); phiStates = storm::storage::BitVector(mdp.getNumberOfStates(), true); psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h index 4cf453c738..5a837289ae 100644 --- a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h @@ -2157,8 +2157,8 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); result.phiStates = leftQualitativeResult.getTruthValuesVector(); result.psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -2167,7 +2167,7 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); result.phiStates = storm::storage::BitVector(model.getNumberOfStates(), true); result.psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-dft/modelchecker/DFTModelChecker.cpp b/src/storm-dft/modelchecker/DFTModelChecker.cpp index 6dbbc1f31a..e56ed46673 100644 --- a/src/storm-dft/modelchecker/DFTModelChecker.cpp +++ b/src/storm-dft/modelchecker/DFTModelChecker.cpp @@ -461,7 +461,7 @@ std::vector DFTModelChecker::checkModel(std::shared_ptr(model, storm::api::createTask(property, true))); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); ValueType resultValue = result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second; results.push_back(resultValue); } else { diff --git a/src/storm-pars-cli/sampling.h b/src/storm-pars-cli/sampling.h index 622f806415..b163dabe3f 100644 --- a/src/storm-pars-cli/sampling.h +++ b/src/storm-pars-cli/sampling.h @@ -115,7 +115,7 @@ void verifyPropertiesAtSamplePoints(ModelType const& model, cli::SymbolicInput c valuationWatch.stop(); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); } printInitialStatesResult(result, &valuationWatch, &valuation); diff --git a/src/storm-pars-cli/solutionFunctions.h b/src/storm-pars-cli/solutionFunctions.h index 294c50c56b..8c74e278ff 100644 --- a/src/storm-pars-cli/solutionFunctions.h +++ b/src/storm-pars-cli/solutionFunctions.h @@ -31,7 +31,7 @@ void computeSolutionFunctionsWithSparseEngine(std::shared_ptr result = storm::api::verifyWithSparseEngine(model, storm::api::createTask(formula, true)); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); } return result; }, diff --git a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp index 5bf5ec4f12..ce1ae41f60 100644 --- a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp +++ b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp @@ -143,20 +143,20 @@ void SparseDerivativeInstantiationModelChecker::spec if (this->currentFormula->isRewardOperatorFormula()) { auto subformula = modelchecker::CheckTask( this->currentFormula->asRewardOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { if (this->currentFormula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { auto rightSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()); auto leftSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()); - target = propositionalChecker.check(rightSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); - avoid = propositionalChecker.check(leftSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); avoid.complement(); } else { auto subformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } } initialStateModel = model.getStates("init").getNextSetIndex(0); diff --git a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp index 6b7387b67c..6551db7209 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp @@ -181,7 +181,7 @@ std::unique_ptr SparseDtmcInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp index dc75828481..d866cc858b 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp @@ -220,7 +220,7 @@ std::unique_ptr SparseMdpInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 11ada9bdd9..150f271501 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -151,9 +151,9 @@ void SparseDtmcParameterLiftingModelCheckerasExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -193,9 +193,9 @@ void SparseDtmcParameterLiftingModelCheckerasExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -265,7 +265,7 @@ void SparseDtmcParameterLiftingModelCheckerasExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index 9e9c2f366f..ff81f266b4 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -110,9 +110,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -153,9 +153,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -204,7 +204,7 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp index 69964a1cff..0cb3c6a252 100644 --- a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp @@ -101,15 +101,16 @@ RegionResult SparseParameterLiftingModelChecker:: (result == RegionResult::Unknown || result == RegionResult::ExistsIllDefined || result == RegionResult::CenterIllDefined)) { auto const center = region.region.getCenterPoint(); if (getInstantiationChecker(false).isWellDefined(center)) { - result = getInstantiationChecker(false).check(env, center)->asExplicitQualitativeCheckResult()[getUniqueInitialState()] + result = getInstantiationChecker(false).check(env, center)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()] ? RegionResult::CenterSat : RegionResult::CenterViolated; } else { auto const lowerCorner = region.region.getLowerBoundaries(); if (getInstantiationChecker(false).isWellDefined(lowerCorner)) { - result = getInstantiationChecker(false).check(env, lowerCorner)->asExplicitQualitativeCheckResult()[getUniqueInitialState()] - ? RegionResult::ExistsSat - : RegionResult::ExistsViolated; + result = + getInstantiationChecker(false).check(env, lowerCorner)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()] + ? RegionResult::ExistsSat + : RegionResult::ExistsViolated; } else { result = RegionResult::CenterIllDefined; } @@ -143,7 +144,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto const valuation = getOptimalValuationForMonotonicity(region.region, globalMonotonicity->getMonotonicityResult(), dirToCheck); STORM_LOG_ASSERT(valuation.size() == region.region.getVariables().size(), "Not all parameters seem to be monotonic."); auto& checker = existsSat ? getInstantiationCheckerSAT(false) : getInstantiationCheckerVIO(false); - bool const monCheckResult = checker.check(env, valuation)->asExplicitQualitativeCheckResult()[getUniqueInitialState()]; + bool const monCheckResult = checker.check(env, valuation)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]; if (existsSat == monCheckResult) { result = existsSat ? RegionResult::AllSat : RegionResult::AllViolated; STORM_LOG_INFO("Region " << region.region << " is " << result << ", discovered with instantiation checker on " << valuation @@ -165,7 +166,7 @@ RegionResult SparseParameterLiftingModelChecker:: // Try to prove AllSat or AllViolated through parameterLifting auto const checkResult = this->check(env, region, dirToCheck); if (checkResult) { - bool const value = checkResult->asExplicitQualitativeCheckResult()[getUniqueInitialState()]; + bool const value = checkResult->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]; if ((dirToCheck == dirForSat) == value) { result = (dirToCheck == dirForSat) ? RegionResult::AllSat : RegionResult::AllViolated; } else if (sampleVerticesOfRegion) { @@ -196,7 +197,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto vertices = region.getVerticesOfRegion(region.getVariables()); auto vertexIt = vertices.begin(); while (vertexIt != vertices.end() && !(hasSatPoint && hasViolatedPoint)) { - if (getInstantiationChecker(false).check(env, *vertexIt)->asExplicitQualitativeCheckResult()[getUniqueInitialState()]) { + if (getInstantiationChecker(false).check(env, *vertexIt)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]) { hasSatPoint = true; } else { hasViolatedPoint = true; diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp index 05fa65ef00..184b549475 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp @@ -91,8 +91,9 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; + bool preciseResult = + preciseChecker.check(env, region, parameterOptDir) + ->template asExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; bool preciseResultAgrees = preciseResult == (currentResult == RegionResult::AllSat); if (!preciseResultAgrees) { @@ -103,8 +104,9 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; + preciseResult = + preciseChecker.check(env, region, parameterOptDir) + ->template asExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; if (preciseResult && parameterOptDir == preciseChecker.getCurrentCheckTask().getOptimizationDirection()) { currentResult = RegionResult::AllSat; } else if (!preciseResult && parameterOptDir == storm::solver::invert(preciseChecker.getCurrentCheckTask().getOptimizationDirection())) { diff --git a/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp b/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp index 90cabf4968..a57d2d9ead 100644 --- a/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp +++ b/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp @@ -102,16 +102,16 @@ std::shared_ptr OrderExtender::getBottomTopOrder assert(formula->isProbabilityOperatorFormula()); if (formula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { phiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } else { assert(formula->asProbabilityOperatorFormula().getSubformula().isEventuallyFormula()); phiStates = storage::BitVector(numberOfStates, true); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } // Get the maybeStates diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index 7258cbb5b2..ea66d7728e 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -30,9 +30,9 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -97,10 +97,10 @@ bool SparseParametricDtmcSimplifier::simplifyForBoundedUntilPro return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = storm::utility::graph::performProbGreater0(this->originalModel.getBackwardTransitions(), phiStates, psiStates, true, upperStepBound); @@ -152,7 +152,7 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 375690682f..4026d9dcfb 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -35,9 +35,9 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -121,10 +121,10 @@ bool SparseParametricMdpSimplifier::simplifyForBoundedUntilProb return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = minimizing ? storm::utility::graph::performProbGreater0A(this->originalModel.getTransitionMatrix(), @@ -182,7 +182,7 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm-permissive/analysis/PermissiveSchedulers.cpp b/src/storm-permissive/analysis/PermissiveSchedulers.cpp index 5ce205bc4d..a73a11c45f 100644 --- a/src/storm-permissive/analysis/PermissiveSchedulers.cpp +++ b/src/storm-permissive/analysis/PermissiveSchedulers.cpp @@ -20,8 +20,9 @@ boost::optional> computePermissiveSchedulerViaMILP storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); @@ -49,8 +50,9 @@ boost::optional> computePermissiveSchedulerViaSMT( storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); diff --git a/src/storm-pomdp-cli/storm-pomdp.cpp b/src/storm-pomdp-cli/storm-pomdp.cpp index 45805c4cc7..45f5595dcb 100644 --- a/src/storm-pomdp-cli/storm-pomdp.cpp +++ b/src/storm-pomdp-cli/storm-pomdp.cpp @@ -273,7 +273,7 @@ bool performAnalysis(std::shared_ptr> co storm::api::createTask(formula.asSharedPointer(), true)); if (resultPtr) { auto result = resultPtr->template asExplicitQuantitativeCheckResult(); - result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); + result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); if (storm::utility::resources::isTerminate()) { STORM_PRINT_AND_LOG("\nResult till abort: "); } else { diff --git a/src/storm-pomdp/analysis/FormulaInformation.cpp b/src/storm-pomdp/analysis/FormulaInformation.cpp index 3b7ad31bbf..62aaee7078 100644 --- a/src/storm-pomdp/analysis/FormulaInformation.cpp +++ b/src/storm-pomdp/analysis/FormulaInformation.cpp @@ -114,7 +114,7 @@ template storm::storage::BitVector getStates(storm::logic::Formula const& propositionalFormula, bool formulaInverted, PomdpType const& pomdp) { storm::modelchecker::SparsePropositionalModelChecker mc(pomdp); auto checkResult = mc.check(propositionalFormula); - storm::storage::BitVector resultBitVector(checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector resultBitVector(checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); if (formulaInverted) { resultBitVector.complement(); } diff --git a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp index 3f0f71845c..5a9a6fcea5 100644 --- a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp +++ b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp @@ -202,7 +202,7 @@ storm::storage::BitVector QualitativeAnalysisOnGraphs::checkPropositi storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class QualitativeAnalysisOnGraphs; diff --git a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp index a357cc5917..a8f1f388a6 100644 --- a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp +++ b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp @@ -234,7 +234,7 @@ storm::storage::BitVector GlobalPomdpMecChoiceEliminator::checkPropos storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class GlobalPomdpMecChoiceEliminator; diff --git a/src/storm/api/export.h b/src/storm/api/export.h index c24ea4ce33..baff690a6b 100644 --- a/src/storm/api/export.h +++ b/src/storm/api/export.h @@ -115,7 +115,8 @@ inline void exportCheckResultToJson(std::shared_ptrisExplicitQualitativeCheckResult()) { - auto j = checkResult->asExplicitQualitativeCheckResult().toJson(model->getOptionalStateValuations(), model->getStateLabeling()); + auto j = checkResult->template asExplicitQualitativeCheckResult().template toJson(model->getOptionalStateValuations(), + model->getStateLabeling()); stream << storm::dumpJson(j); } else { STORM_LOG_THROW(checkResult->isExplicitQuantitativeCheckResult(), storm::exceptions::NotSupportedException, diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index f81331c3d2..6b42c5be6c 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -150,7 +150,7 @@ std::unique_ptr AbstractModelChecker::computeStateFormul std::unique_ptr resultPointer = this->check(env, checkTask.getFormula()); if (resultPointer->isExplicitQualitativeCheckResult()) { STORM_LOG_ASSERT(ModelType::Representation == storm::models::ModelRepresentation::Sparse, "Unexpected model type."); - return std::make_unique>(resultPointer->asExplicitQualitativeCheckResult()); + return std::make_unique>(resultPointer->template asExplicitQualitativeCheckResult()); } else { STORM_LOG_ASSERT(resultPointer->isSymbolicQualitativeCheckResult(), "Unexpected result type."); STORM_LOG_ASSERT(ModelType::Representation != storm::models::ModelRepresentation::Sparse, "Unexpected model type."); diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 8a5e847156..b36579b09c 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -57,8 +57,8 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported."); @@ -86,7 +86,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -97,7 +97,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), probabilisticTransitions, probabilisticTransitions.transpose(), @@ -111,8 +111,8 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), @@ -130,7 +130,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -148,7 +148,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -196,7 +196,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -220,7 +220,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(probabilisticTransitions, this->getModel().getExitRateVector()); @@ -246,7 +246,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -269,8 +269,8 @@ std::vector SparseCtmcCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeAllTransientProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), leftResult.getTruthValuesVector(), diff --git a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index 203cbce8f1..f5aa67bc85 100644 --- a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -72,10 +72,10 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded and reward-bounded properties on MAs are not supported."); @@ -103,7 +103,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -116,7 +116,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -135,8 +135,8 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeUntilProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), @@ -157,7 +157,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -183,7 +183,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -205,7 +205,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute reachability rewards in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityRewards( @@ -247,7 +247,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute long-run average in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper( this->getModel().getTransitionMatrix(), this->getModel().getMarkovianStates(), this->getModel().getExitRates()); @@ -291,7 +291,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute expected times in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityTimes( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), diff --git a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp index 225b7b12f5..4bfd4de17f 100644 --- a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp @@ -34,7 +34,7 @@ template std::unique_ptr SparseCbAchievabilityQuery::check(Environment const& env) { bool result = this->checkAchievability(); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp index cedca9edfe..75bdfe5c8b 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp @@ -63,13 +63,13 @@ std::unique_ptr DeterministicSchedsAchievabilityCheckercheck(env, thresholdPolytope, eps); bool const isAchievable = achievingPoint.has_value(); + using ValueType = typename SparseModelType::ValueType; if (isAchievable) { STORM_LOG_INFO( "Found achievable point: " << storm::utility::vector::toString(achievingPoint->first) << " ( approx. " << storm::utility::vector::toString(storm::utility::vector::convertNumericVector(achievingPoint->first)) << " )."); if (optimizingObjectiveIndex.has_value()) { - using ValueType = typename SparseModelType::ValueType; // Average between obtained lower- and upper bounds auto result = storm::utility::convertNumber(achievingPoint->first[*optimizingObjectiveIndex] + achievingPoint->second); @@ -80,7 +80,7 @@ std::unique_ptr DeterministicSchedsAchievabilityChecker>(originalModelInitialState, result); } } - return std::make_unique(originalModelInitialState, isAchievable); + return std::make_unique>(originalModelInitialState, isAchievable); } template class DeterministicSchedsAchievabilityChecker, storm::RationalNumber>; diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp index 0346b41e4f..c1d03129b9 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp @@ -39,7 +39,7 @@ storm::storage::BitVector evaluatePropositionalFormula(ModelType const& model, s auto checkResult = mc.check(formula); STORM_LOG_THROW(checkResult && checkResult->isExplicitQualitativeCheckResult(), storm::exceptions::UnexpectedException, "Unexpected type of check result for subformula " << formula << "."); - return checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp index 9271fe33e6..562f4dbfc5 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp @@ -51,7 +51,8 @@ std::unique_ptr SparsePcaaAchievabilityQuerycheckAchievability(env); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp index c13762c22e..e4e613f69a 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp @@ -91,7 +91,8 @@ std::unique_ptr SparsePcaaQuantitativeQuery(new ExplicitQuantitativeCheckResult( this->originalModel.getInitialStates().getNextSetIndex(0), resultForOriginalModel)); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); } } diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 6eabbd6bda..1a51f2cafc 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -139,9 +139,9 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +151,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +161,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +181,7 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,13 +210,13 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); } } else if (opFormula->isLongRunAverageOperatorFormula()) { - auto lraStates = mc.check(pathFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lraStates = mc.check(pathFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Compute Sat(Forall F (Forall G not "lraStates")) auto forallGloballyNotLraStates = storm::utility::graph::performProb0A(backwardTransitions, ~lraStates, lraStates); absorbingStatesForSubformula = storm::utility::graph::performProb1A(model->getTransitionMatrix(), model->getNondeterministicChoiceIndices(), @@ -432,7 +432,7 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +445,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +455,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +542,7 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp index 344766e323..81815a9d85 100644 --- a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp @@ -176,7 +176,7 @@ std::unique_ptr HybridMdpPrctlModelChecker::checkMultiOb // Convert the explicit result if (explicitResult->isExplicitQualitativeCheckResult()) { - if (explicitResult->asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { + if (explicitResult->template asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { return std::unique_ptr(new storm::modelchecker::SymbolicQualitativeCheckResult( this->getModel().getReachableStates(), this->getModel().getInitialStates(), this->getModel().getManager().getBddOne())); } else { diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 1686bbe010..431039c622 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -92,8 +92,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper step bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -109,7 +109,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -121,8 +121,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -135,7 +135,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet()); @@ -151,7 +151,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -168,7 +168,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -236,7 +236,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -249,7 +249,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.getHint()); @@ -290,7 +290,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); @@ -320,8 +320,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -340,8 +340,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asReachabilityRewardFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index e532228189..8d19c3dea6 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -139,8 +139,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to have discrete upper time bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -158,7 +158,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -172,8 +172,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -192,7 +192,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -215,7 +215,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -245,7 +245,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -276,8 +276,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); if constexpr (std::is_same_v) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { @@ -363,7 +363,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -383,7 +383,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), @@ -446,7 +446,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); @@ -499,7 +499,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto ret = lexicographic::check(env, this->getModel(), checkTask, formulaChecker); std::unique_ptr result(new LexicographicCheckResult(ret.values, *this->getModel().getInitialStates().begin())); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 7bb836cc88..02b9e2f177 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -133,8 +133,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +155,7 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +426,9 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp index 094a2332cf..8fa08b56c7 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -35,9 +35,9 @@ std::unique_ptr SparsePropositionalModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::BooleanLiteralFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isTrueFormula()) { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); } } @@ -47,7 +47,7 @@ std::unique_ptr SparsePropositionalModelChecker::c storm::logic::AtomicLabelFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(model.hasLabel(stateFormula.getLabel()), storm::exceptions::InvalidPropertyException, "The property refers to unknown label '" << stateFormula.getLabel() << "'."); - return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); } template diff --git a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 43296a4d13..506f03b3ff 100644 --- a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -55,7 +55,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); - storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::SparseMatrix const& transitionMatrix = this->getModel().getTransitionMatrix(); uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); @@ -112,7 +112,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -177,7 +177,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -350,8 +350,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Start by determining the states that have a non-zero probability of reaching the target states within the // time bound. @@ -444,7 +444,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); + checkResult->filter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); } return checkResult; } @@ -457,8 +457,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); return computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, checkTask.isOnlyInitialStatesRelevantSet()); @@ -538,7 +538,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker subResultPointer = this->check(eventuallyFormula.getSubformula()); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& targetStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); @@ -650,8 +650,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - storm::storage::BitVector phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); // Do some sanity checks to establish some required properties. diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 8549ce26d0..c43c2cf441 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -82,12 +82,14 @@ bool CheckResult::isHybridQuantitativeCheckResult() const { return false; } -ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { + return dynamic_cast&>(*this); } -ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { + return dynamic_cast const&>(*this); } template @@ -188,6 +190,8 @@ template QuantitativeCheckResult const& CheckResult::asQuantitativeCheck template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; template LexicographicCheckResult& CheckResult::asLexicographicCheckResult(); @@ -221,6 +225,8 @@ template QuantitativeCheckResult const& CheckResult::asQu template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; @@ -228,6 +234,9 @@ template QuantitativeCheckResult const& CheckResult::as template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; @@ -235,5 +244,10 @@ template LexicographicCheckResult& CheckResult::asLexicog template LexicographicCheckResult const& CheckResult::asLexicographicCheckResult() const; #endif + +// Instantiation for storm::Interval (carl::Interval) +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/CheckResult.h b/src/storm/modelchecker/results/CheckResult.h index f46e1abcf9..c8ba918329 100644 --- a/src/storm/modelchecker/results/CheckResult.h +++ b/src/storm/modelchecker/results/CheckResult.h @@ -13,6 +13,7 @@ namespace modelchecker { class QualitativeCheckResult; template class QuantitativeCheckResult; +template class ExplicitQualitativeCheckResult; template @@ -77,8 +78,11 @@ class CheckResult { template QuantitativeCheckResult const& asQuantitativeCheckResult() const; - ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; + template + ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); + + template + ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; template ExplicitQuantitativeCheckResult& asExplicitQuantitativeCheckResult(); diff --git a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp index a9d59197a5..ac58ec1fc2 100644 --- a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp @@ -56,8 +56,8 @@ void ExplicitParetoCurveCheckResult::filter(QualitativeCheckResult co STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index f608a3065b..9404a7c355 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -3,53 +3,67 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/adapters/JsonAdapter.h" +#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/utility/macros.h" namespace storm { namespace modelchecker { -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { + +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { boost::get(truthValues)[state] = value; } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) + : truthValues(std::move(truthValues)) { // Intentionally left empty. } -std::unique_ptr ExplicitQualitativeCheckResult::clone() const { - return std::make_unique(this->truthValues); +template +std::unique_ptr ExplicitQualitativeCheckResult::clone() const { + return std::make_unique>(this->truthValues); } -void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, bool logicalAnd) { +template +void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, + bool logicalAnd) { STORM_LOG_THROW(second.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); STORM_LOG_THROW(first.isResultForAllStates() == second.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); - ExplicitQualitativeCheckResult const& secondCheckResult = static_cast(second); + ExplicitQualitativeCheckResult const& secondCheckResult = static_cast const&>(second); if (first.isResultForAllStates()) { if (logicalAnd) { boost::get(first.truthValues) &= boost::get(secondCheckResult.truthValues); @@ -78,17 +92,20 @@ void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitative } } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, true); return *this; } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, false); return *this; } -bool ExplicitQualitativeCheckResult::existsTrue() const { +template +bool ExplicitQualitativeCheckResult::existsTrue() const { if (this->isResultForAllStates()) { return !boost::get(truthValues).empty(); } else { @@ -100,7 +117,9 @@ bool ExplicitQualitativeCheckResult::existsTrue() const { return false; } } -bool ExplicitQualitativeCheckResult::forallTrue() const { + +template +bool ExplicitQualitativeCheckResult::forallTrue() const { if (this->isResultForAllStates()) { return boost::get(truthValues).full(); } else { @@ -113,7 +132,8 @@ bool ExplicitQualitativeCheckResult::forallTrue() const { } } -uint64_t ExplicitQualitativeCheckResult::count() const { +template +uint64_t ExplicitQualitativeCheckResult::count() const { if (this->isResultForAllStates()) { return boost::get(truthValues).getNumberOfSetBits(); } else { @@ -127,7 +147,8 @@ uint64_t ExplicitQualitativeCheckResult::count() const { } } -bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { +template +bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { if (this->isResultForAllStates()) { return boost::get(truthValues).get(state); } else { @@ -138,15 +159,18 @@ bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_ty } } -ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { +template +typename ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { return boost::get(truthValues); } -ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { +template +typename ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { return boost::get(truthValues); } -void ExplicitQualitativeCheckResult::complement() { +template +void ExplicitQualitativeCheckResult::complement() { if (this->isResultForAllStates()) { boost::get(truthValues).complement(); } else { @@ -156,19 +180,23 @@ void ExplicitQualitativeCheckResult::complement() { } } -bool ExplicitQualitativeCheckResult::isExplicit() const { +template +bool ExplicitQualitativeCheckResult::isExplicit() const { return true; } -bool ExplicitQualitativeCheckResult::isResultForAllStates() const { +template +bool ExplicitQualitativeCheckResult::isResultForAllStates() const { return truthValues.which() == 0; } -bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { +template +bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { return true; } -std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { +template +std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { if (this->isResultForAllStates()) { vector_type const& vector = boost::get(truthValues); bool allTrue = vector.full(); @@ -211,11 +239,12 @@ std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) c return out; } -void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { +template +void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { @@ -259,9 +288,10 @@ void insertJsonEntry(storm::json& json, uint64_t const& id, bo json.push_back(std::move(entry)); } +template template -storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, - std::optional const& stateLabels) const { +storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, + std::optional const& stateLabels) const { storm::json result; if (this->isResultForAllStates()) { vector_type const& valuesAsVector = boost::get(truthValues); @@ -277,10 +307,33 @@ storm::json ExplicitQualitativeCheckResult::toJson(std::option return result; } -template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, - std::optional const&) const; -template storm::json ExplicitQualitativeCheckResult::toJson( +// Explicit template instantiations +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; + +#ifdef STORM_HAVE_CARL +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; +#endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 8e13acbef7..9e67d1b277 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -9,12 +9,15 @@ #include "storm/modelchecker/results/QualitativeCheckResult.h" #include "storm/models/sparse/StateLabeling.h" #include "storm/storage/BitVector.h" +#include "storm/storage/Scheduler.h" #include "storm/storage/sparse/StateType.h" #include "storm/storage/sparse/StateValuations.h" namespace storm { namespace modelchecker { + +template class ExplicitQualitativeCheckResult : public QualitativeCheckResult { public: typedef storm::storage::BitVector vector_type; @@ -69,6 +72,9 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { // The values of the quantitative check result. boost::variant truthValues; + + // An optional scheduler that accompanies the values. + boost::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 3464ee9381..278ef000b4 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -61,7 +61,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boos } template -ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { +ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { if (other.isResultForAllStates()) { storm::storage::BitVector const& bvValues = other.getTruthValuesVector(); @@ -73,7 +73,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(Expl values = newVector; } else { - ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); + typename ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); map_type newMap; for (auto const& e : bitMap) { @@ -109,8 +109,8 @@ void ExplicitQuantitativeCheckResult::filter(QualitativeCheckResult c STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { map_type newMap; @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } } diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index e9c9ac487d..125752ca14 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -16,6 +16,7 @@ namespace storm { namespace modelchecker { // Forward declaration +template class ExplicitQualitativeCheckResult; template @@ -39,7 +40,7 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult const& other); virtual ~ExplicitQuantitativeCheckResult() = default; diff --git a/src/storm/modelchecker/results/LexicographicCheckResult.cpp b/src/storm/modelchecker/results/LexicographicCheckResult.cpp index 027f21f3ef..0206554088 100644 --- a/src/storm/modelchecker/results/LexicographicCheckResult.cpp +++ b/src/storm/modelchecker/results/LexicographicCheckResult.cpp @@ -43,8 +43,8 @@ void LexicographicCheckResult::filter(QualitativeCheckResult const& f STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp index 4828c13ef7..2f3206ac29 100644 --- a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp +++ b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp @@ -160,8 +160,8 @@ void BisimulationDecomposition::Options::checkAndSetMe storm::modelchecker::SparsePropositionalModelChecker checker(model); std::unique_ptr phiStatesCheckResult = checker.check(*leftSubformula); std::unique_ptr psiStatesCheckResult = checker.check(*rightSubformula); - phiStates = phiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); - psiStates = psiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + phiStates = phiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = psiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { optimalityType = boost::none; } diff --git a/src/storm/transformer/MemoryIncorporation.cpp b/src/storm/transformer/MemoryIncorporation.cpp index a0d894e6a3..14554ec711 100644 --- a/src/storm/transformer/MemoryIncorporation.cpp +++ b/src/storm/transformer/MemoryIncorporation.cpp @@ -27,7 +27,8 @@ storm::storage::MemoryStructure getGoalMemory(SparseModelType const& model, stor "The subformula " << propositionalGoalStateFormula << " should be propositional."); storm::modelchecker::SparsePropositionalModelChecker mc(model); - storm::storage::BitVector goalStates = mc.check(propositionalGoalStateFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = + mc.check(propositionalGoalStateFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied for all initial states. In such a case the trivial memory structure suffices. if (model.getInitialStates().isSubsetOf(goalStates)) { diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp index ceab40c2fe..4abd1731d5 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp @@ -52,7 +52,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -100,7 +100,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -149,7 +149,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -202,7 +202,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -256,7 +256,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp index 0c865a12ea..cf556ea3a0 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp @@ -144,7 +144,7 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -191,7 +191,7 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -268,7 +268,7 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -359,7 +359,7 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -412,7 +412,7 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp index b3c587afd2..46ab3d299b 100644 --- a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp @@ -55,7 +55,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -63,7 +63,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); } diff --git a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp index 84594a1389..99aa4fa1b8 100644 --- a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp @@ -49,7 +49,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -57,7 +57,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); diff --git a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp index e546e33be6..2692e8c546 100644 --- a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp @@ -318,7 +318,7 @@ class CtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp index c7273dd2a4..36e162ab5b 100644 --- a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp @@ -381,7 +381,7 @@ class LraCtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp index 4010abee25..3a398d1b1e 100644 --- a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp @@ -245,7 +245,7 @@ class MarkovAutomatonCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp index 755a60f403..42fd7aa01e 100644 --- a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp @@ -274,13 +274,13 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { @@ -293,7 +293,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } @@ -359,7 +359,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } ++formulaIndex; @@ -371,7 +371,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp index 94df68f83b..074797ec94 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp @@ -43,9 +43,9 @@ TEST_F(SparseMaCbMultiObjectiveModelCheckerTest, server) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp index 74a47f3f6a..f4a19f9597 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp @@ -172,12 +172,12 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_achievability_3Obj std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) { @@ -210,7 +210,7 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_pareto_2Obj) { diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp index baa4726654..16250a581f 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp @@ -43,11 +43,11 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { @@ -69,7 +69,7 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } /* This test takes a little bit too long ... @@ -88,6 +88,6 @@ formulas)->as>(); uint_fast64_ std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(*mdp, formulas[0]->asMultiObjectiveFormula()) ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } */ diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp index d08c62033d..8a40aa4161 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp @@ -228,11 +228,11 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, zeroconf) { @@ -304,7 +304,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, tiny_rewards_negative) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { @@ -328,7 +328,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, dpm) { diff --git a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp index 5083138f3b..a5a8fe0e26 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp @@ -644,7 +644,7 @@ class DtmcPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp index 8c01df8684..26d4b4622e 100644 --- a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp @@ -670,7 +670,7 @@ class MdpPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp index 635b352b69..c2204c444d 100644 --- a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp @@ -164,7 +164,7 @@ class QuantileQueryTest : public ::testing::Test { std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) const { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } }; diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 27a9254a16..3d509f2fbc 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -17,11 +17,11 @@ std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, From ee9f051ecc3d6094efe8280296ed56756c45c1e5 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:44:13 +0100 Subject: [PATCH 071/102] Remember scheduler from quantitative scheduler when applying bounds --- resources/3rdparty/l3pp | 1 + .../ExplicitQualitativeCheckResult.cpp | 31 +++++++++++++++++-- .../results/ExplicitQualitativeCheckResult.h | 11 +++++-- .../ExplicitQuantitativeCheckResult.cpp | 4 +-- 4 files changed, 40 insertions(+), 7 deletions(-) create mode 160000 resources/3rdparty/l3pp diff --git a/resources/3rdparty/l3pp b/resources/3rdparty/l3pp new file mode 160000 index 0000000000..e4f8d7fe6c --- /dev/null +++ b/resources/3rdparty/l3pp @@ -0,0 +1 @@ +Subproject commit e4f8d7fe6c328849aff34d2dfd6fd592c14070d5 diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 9404a7c355..f39ac58a74 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -41,13 +41,16 @@ ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm: } template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues, + boost::optional>> scheduler) + : truthValues(truthValues), scheduler(scheduler) { // Intentionally left empty. } template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) - : truthValues(std::move(truthValues)) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues, + boost::optional>> scheduler) + : truthValues(std::move(truthValues)), scheduler(scheduler) { // Intentionally left empty. } @@ -270,6 +273,28 @@ void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult co } } +template +bool ExplicitQualitativeCheckResult::hasScheduler() const { + return static_cast(scheduler); +} + +template +void ExplicitQualitativeCheckResult::setScheduler(std::unique_ptr>&& scheduler) { + this->scheduler = std::move(scheduler); +} + +template +storm::storage::Scheduler const& ExplicitQualitativeCheckResult::getScheduler() const { + STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + return *scheduler.get(); +} + +template +storm::storage::Scheduler& ExplicitQualitativeCheckResult::getScheduler() { + STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + return *scheduler.get(); +} + template void insertJsonEntry(storm::json& json, uint64_t const& id, bool value, std::optional const& stateValuations = std::nullopt, diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 9e67d1b277..14d781ef86 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -30,8 +30,10 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value); ExplicitQualitativeCheckResult(vector_type const& truthValues); ExplicitQualitativeCheckResult(vector_type&& truthValues); - ExplicitQualitativeCheckResult(boost::variant const& truthValues); - ExplicitQualitativeCheckResult(boost::variant&& truthValues); + ExplicitQualitativeCheckResult(boost::variant const& truthValues, + boost::optional>> scheduler = boost::none); + ExplicitQualitativeCheckResult(boost::variant&& truthValues, + boost::optional>> scheduler = boost::none); ExplicitQualitativeCheckResult(ExplicitQualitativeCheckResult const& other) = default; ExplicitQualitativeCheckResult& operator=(ExplicitQualitativeCheckResult const& other) = default; @@ -63,6 +65,11 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { virtual void filter(QualitativeCheckResult const& filter) override; + virtual bool hasScheduler() const override; + void setScheduler(std::unique_ptr>&& scheduler); + storm::storage::Scheduler const& getScheduler() const; + storm::storage::Scheduler& getScheduler(); + template storm::json toJson(std::optional const& stateValuations = std::nullopt, std::optional const& stateLabels = std::nullopt) const; diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 278ef000b4..f9dc8f2bef 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result), std::move(scheduler))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result), std::move(scheduler))); } } From 1868e4421eb6c70c37c5f8a7b030ffa4271c91f9 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:49:56 +0100 Subject: [PATCH 072/102] Export schedulers for qualitative models in the cli --- src/storm-cli-utilities/model-handling.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 6f7eaee4b2..62dc3a4279 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -1348,6 +1348,13 @@ void verifyModel(std::shared_ptr> const& auto const& paretoRes = result->template asExplicitParetoCurveCheckResult(); storm::api::exportParetoScheduler(sparseModel, paretoRes.getPoints(), paretoRes.getSchedulers(), schedulerExportPath.string()); } + } else if (result->isExplicitQualitativeCheckResult()) { + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export for interval models is not supported."); + } else { + storm::api::exportScheduler(sparseModel, result->template asExplicitQualitativeCheckResult().getScheduler(), + schedulerExportPath.string()); + } } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export not supported for this value type."); } From 0da7fd862ebf3fc3938d951481f0b5f35e022d1a Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 15:21:40 +0100 Subject: [PATCH 073/102] Fix test --- .../transformer/IntervalEndComponentPreserverCheckTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp b/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp index bdc748e6e0..6fd2a97347 100644 --- a/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp +++ b/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp @@ -53,7 +53,7 @@ void testModelInterval(std::string programFile, std::string formulaAsString, std storm::modelchecker::SparsePropositionalModelChecker> propositionalChecker(*dtmc); storm::storage::BitVector psiStates = propositionalChecker.check(checkTask.getFormula().asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); std::vector target(model->getNumberOfStates(), storm::utility::zero()); From 798d3e4f0e49c64cc3560e2429e38ff00ddfac4f Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 15:25:11 +0100 Subject: [PATCH 074/102] Format --- src/storm-cli-utilities/model-handling.h | 18 +++---- ...SparseDtmcParameterLiftingModelChecker.cpp | 25 ++++++---- .../SparseMdpParameterLiftingModelChecker.cpp | 25 ++++++---- .../SparseParametricDtmcSimplifier.cpp | 15 +++--- .../SparseParametricMdpSimplifier.cpp | 15 +++--- .../SparseMultiObjectivePreprocessor.cpp | 48 ++++++++++++------- .../helper/rewardbounded/ProductModel.cpp | 18 ++++--- .../monotonicity/MonotonicityCheckerTest.cpp | 15 ++++-- .../region/monotonicity/OrderExtenderTest.cpp | 15 ++++-- 9 files changed, 121 insertions(+), 73 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 62dc3a4279..1e81947d93 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -903,14 +903,14 @@ inline void printCounterexample(std::shared_ptr -requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, - SymbolicInput const&) { + requires(!std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template -requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, - SymbolicInput const& input) { + requires(std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -966,8 +966,8 @@ requires(std::derived_from>) inl } template -requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, - storm::modelchecker::FilterType ft) { + requires(!storm::IsIntervalType) +void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1034,9 +1034,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template -requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, - storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { + requires(!storm::IsIntervalType) +void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 150f271501..002151ac7c 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -150,10 +150,12 @@ void SparseDtmcParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -192,10 +194,12 @@ void SparseDtmcParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -264,8 +268,9 @@ void SparseDtmcParameterLiftingModelChecker propositionalChecker(*this->parametricModel); STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(checkTask.getFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index ff81f266b4..4294ad72b5 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -109,10 +109,12 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -152,10 +154,12 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -203,8 +207,9 @@ void SparseMdpParameterLiftingModelChecker::speci storm::modelchecker::SparsePropositionalModelChecker propositionalChecker(*this->parametricModel); STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(checkTask.getFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index ea66d7728e..2910fa4881 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -29,10 +29,12 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit STORM_LOG_DEBUG("Can not simplify when Until-formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -151,8 +153,9 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew STORM_LOG_DEBUG("Can not simplify when reachability reward formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 4026d9dcfb..ed9ac1efbe 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -34,10 +34,12 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti STORM_LOG_DEBUG("Can not simplify when Until-formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -181,8 +183,9 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa STORM_LOG_DEBUG("Can not simplify when reachability reward formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 1a51f2cafc..91dc7be1b2 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,10 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = + mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = + mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -138,10 +140,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector absorbingStatesForSubSubformula; for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); - auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i)) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i)) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +155,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +169,14 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +191,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,7 +221,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); @@ -432,7 +444,8 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = + mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +458,8 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = + mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +469,8 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = + mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +557,8 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = + mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 02b9e2f177..ccc196db4e 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -132,9 +132,12 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( for (auto dim : objectiveDimensions[objIndex]) { auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); - constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + constraintStates &= (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +158,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = + mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +430,11 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = + mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = + mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp index 4abd1731d5..9a78b6f47c 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp @@ -52,7 +52,8 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -100,7 +101,8 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -149,7 +151,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -202,7 +205,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -256,7 +260,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp index cf556ea3a0..a50109532e 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp @@ -144,7 +144,8 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -191,7 +192,8 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -268,7 +270,8 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -359,7 +362,8 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -412,7 +416,8 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); From 73e73d8d5552d293002109fe25e24c214aaabb3d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 15:34:29 +0100 Subject: [PATCH 075/102] remove weird git thing --- resources/3rdparty/l3pp | 1 - 1 file changed, 1 deletion(-) delete mode 160000 resources/3rdparty/l3pp diff --git a/resources/3rdparty/l3pp b/resources/3rdparty/l3pp deleted file mode 160000 index e4f8d7fe6c..0000000000 --- a/resources/3rdparty/l3pp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e4f8d7fe6c328849aff34d2dfd6fd592c14070d5 From f3f81e1aff674933e888b528026e6e0a5ae84426 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 17:00:00 +0100 Subject: [PATCH 076/102] fix one ValueType --- .../SparseDerivativeInstantiationModelChecker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp index ce1ae41f60..8f57bb92f7 100644 --- a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp +++ b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp @@ -143,20 +143,20 @@ void SparseDerivativeInstantiationModelChecker::spec if (this->currentFormula->isRewardOperatorFormula()) { auto subformula = modelchecker::CheckTask( this->currentFormula->asRewardOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { if (this->currentFormula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { auto rightSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()); auto leftSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()); - target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); avoid.complement(); } else { auto subformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } } initialStateModel = model.getStates("init").getNextSetIndex(0); From 047d392701881e0940cc9179e4d1f0cfe54fe5ab Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 16 Dec 2025 16:52:15 +0100 Subject: [PATCH 077/102] stuff for the benchmarking --- .../helper/conditional/ConditionalHelper.cpp | 14 +++++++------- .../modules/MinMaxEquationSolverSettings.cpp | 2 +- src/storm/transformer/AddUncertainty.cpp | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index be411d567b..7f7612b20b 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -942,13 +942,13 @@ typename internal::ResultReturnType computeViaBisection(Environment c STORM_LOG_WARN_COND(!env.solver().isForceSoundness(), "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); SolutionType const precision = [&env, boundOption]() { - if (storm::NumberTraits::IsExact || env.solver().isForceExact()) { - // STORM_LOG_WARN_COND(storm::NumberTraits::IsExact && boundOption == BisectionMethodBounds::Advanced, - // "Selected bisection method with exact precision in a setting that might not terminate."); - return storm::utility::zero(); - } else { - return storm::utility::convertNumber(env.solver().minMax().getPrecision()); - } + STORM_LOG_WARN_COND(storm::NumberTraits::IsExact && boundOption == BisectionMethodBounds::Advanced, + "Selected bisection method with exact precision in a setting that might not terminate."); + // if (storm::NumberTraits::IsExact && env.solver().isForceExact()) { + // return storm::utility::zero(); + // } else { + return storm::utility::convertNumber(env.solver().minMax().getPrecision()); + // } }(); bool const relative = env.solver().minMax().getRelativeTerminationCriterion(); diff --git a/src/storm/settings/modules/MinMaxEquationSolverSettings.cpp b/src/storm/settings/modules/MinMaxEquationSolverSettings.cpp index ef674be8ce..7697aebd14 100644 --- a/src/storm/settings/modules/MinMaxEquationSolverSettings.cpp +++ b/src/storm/settings/modules/MinMaxEquationSolverSettings.cpp @@ -54,7 +54,7 @@ MinMaxEquationSolverSettings::MinMaxEquationSolverSettings() : ModuleSettings(mo .setIsAdvanced() .addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to achieve.") .setDefaultValueDouble(1e-06) - .addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorExcluding(0.0, 1.0)) + .addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorIncluding(0.0, 1.0)) .build()) .build()); diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index 7db11d701d..777f3bfb99 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -78,4 +78,5 @@ storm::Interval AddUncertainty::addUncertainty(ValueType const& vt, d } template class AddUncertainty; +template class AddUncertainty; } // namespace storm::transformer \ No newline at end of file From 7e7ddd4f32cee2ad46eb9178a36bc6e01870461c Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 22 Dec 2025 17:49:40 +0100 Subject: [PATCH 078/102] remove unused variable which used a lot of memory --- .../transformer/ObservationTraceUnfolder.cpp | 11 ++++++----- .../transformer/ObservationTraceUnfolder.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index 18f93467cf..c6d2f3bf29 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -14,10 +14,11 @@ ObservationTraceUnfolder::ObservationTraceUnfolder(storm::models::spa std::shared_ptr& exprManager, ObservationTraceUnfolderOptions const& options) : model(model), risk(risk), exprManager(exprManager), options(options) { - statesPerObservation = std::vector(model.getNrObservations() + 1, storm::storage::BitVector(model.getNumberOfStates())); - for (uint64_t state = 0; state < model.getNumberOfStates(); ++state) { - statesPerObservation[model.getObservation(state)].set(state, true); - } + // std::cout << "Starting observation trace unfolder with n obervations " << model.getNrObservations() << "\n"; + // statesPerObservation = std::vector(model.getNrObservations() + 1, storm::storage::BitVector(model.getNumberOfStates())); + // for (uint64_t state = 0; state < model.getNumberOfStates(); ++state) { + // statesPerObservation[model.getObservation(state)].set(state, true); + // } svvar = exprManager->declareFreshIntegerVariable(false, "_s"); tsvar = exprManager->declareFreshIntegerVariable(false, "_t"); } @@ -40,7 +41,7 @@ std::shared_ptr> ObservationTraceUnfolder< STORM_LOG_THROW(actualInitialStates.getNumberOfSetBits() == 1, storm::exceptions::InvalidArgumentException, "Must have unique initial state matching the observation"); // For this z* that only exists in the initial state, we now also define the states for this observation. - statesPerObservation[model.getNrObservations()] = actualInitialStates; + // statesPerObservation[model.getNrObservations()] = actualInitialStates; #ifdef _VERBOSE_OBSERVATION_UNFOLDING std::cout << "build valution builder..\n"; diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h index 55fce6e727..a80d82da27 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.h +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.h @@ -48,7 +48,7 @@ class ObservationTraceUnfolder { storm::models::sparse::Pomdp const& model; std::vector risk; // TODO reconsider holding this as a reference, but there were some strange bugs std::shared_ptr& exprManager; - std::vector statesPerObservation; + // std::vector statesPerObservation; std::vector traceSoFar; storm::expressions::Variable svvar; // Maps to the old state (explicit encoding) storm::expressions::Variable tsvar; // Maps to the time step From ced196151785cc27a46c9a11d16c68bb67b21387 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 24 Dec 2025 02:42:55 +0100 Subject: [PATCH 079/102] Improvements for conditional bisection method * Use acyclic min max solver when possible * enable caching of solver data to avoid some re-allocations * More careful treatment of exact computations --- .../helper/conditional/ConditionalHelper.cpp | 113 ++++++++----- src/storm/utility/RationalApproximation.cpp | 156 ++++++++++++++++++ src/storm/utility/RationalApproximation.h | 18 ++ .../utility/RationalApproximationTest.cpp | 70 ++++++++ 4 files changed, 316 insertions(+), 41 deletions(-) create mode 100644 src/storm/utility/RationalApproximation.cpp create mode 100644 src/storm/utility/RationalApproximation.h create mode 100644 src/test/storm/utility/RationalApproximationTest.cpp diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 62cd911ba7..a23c5f4768 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -15,7 +15,7 @@ #include "storm/storage/SparseMatrix.h" #include "storm/transformer/EndComponentEliminator.h" #include "storm/utility/Extremum.h" -#include "storm/utility/KwekMehlhorn.h" +#include "storm/utility/RationalApproximation.h" #include "storm/utility/SignalHandler.h" #include "storm/utility/graph.h" #include "storm/utility/macros.h" @@ -425,28 +425,38 @@ class WeightedReachabilityHelper { allExceptInit.set(initialStateInSubmatrix, false); eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, conditionRowValues); + isAcyclic = !storm::utility::graph::hasCycle(submatrix); STORM_LOG_INFO("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " - << submatrix.getEntryCount() << " transitions."); + << submatrix.getEntryCount() << " transitions. Matrix is " << (isAcyclic ? "acyclic." : "cyclic.")); } SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, - ValueType const& conditionWeight) const { - auto rowValues = createScaledVector(targetWeight, targetRowValues, conditionWeight, conditionRowValues); + ValueType const& conditionWeight) { + // Set up the solver. + if (!cachedSolver) { + auto solverEnv = env; + if (isAcyclic) { + STORM_LOG_INFO("Using acyclic min-max solver for weighted reachability computation."); + solverEnv.solver().minMax().setMethod(storm::solver::MinMaxMethod::Acyclic); + } + cachedSolver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(solverEnv, submatrix); + cachedSolver->setCachingEnabled(true); + cachedSolver->setOptimizationDirection(dir); + cachedSolver->setRequirementsChecked(); + cachedSolver->setHasUniqueSolution(true); + cachedSolver->setHasNoEndComponents(true); + cachedSolver->setLowerBound(-storm::utility::one()); + cachedSolver->setUpperBound(storm::utility::one()); + } + + // Initialize the right-hand side vector. + createScaledVector(cachedB, targetWeight, targetRowValues, conditionWeight, conditionRowValues); // Initialize the solution vector. - std::vector x(submatrix.getRowGroupCount(), storm::utility::zero()); + cachedX.assign(submatrix.getRowGroupCount(), storm::utility::zero()); - // Set up the solver. - auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(env, submatrix); - solver->setOptimizationDirection(dir); - solver->setRequirementsChecked(); - solver->setHasUniqueSolution(true); - solver->setHasNoEndComponents(true); - solver->setLowerBound(-storm::utility::one()); - solver->setUpperBound(storm::utility::one()); - - solver->solveEquations(env, x, rowValues); - return x[initialStateInSubmatrix]; + cachedSolver->solveEquations(env, cachedX, cachedB); + return cachedX[initialStateInSubmatrix]; } auto getInternalInitialState() const { @@ -512,15 +522,13 @@ class WeightedReachabilityHelper { } private: - std::vector createScaledVector(ValueType const& w1, std::vector const& v1, ValueType const& w2, - std::vector const& v2) const { + void createScaledVector(std::vector& out, ValueType const& w1, std::vector const& v1, ValueType const& w2, + std::vector const& v2) const { STORM_LOG_ASSERT(v1.size() == v2.size(), "Vector sizes must match"); - std::vector result; - result.reserve(v1.size()); + out.resize(v1.size()); for (size_t i = 0; i < v1.size(); ++i) { - result.push_back(w1 * v1[i] + w2 * v2[i]); + out[i] = w1 * v1[i] + w2 * v2[i]; } - return result; } storm::storage::SparseMatrix submatrix; @@ -528,6 +536,10 @@ class WeightedReachabilityHelper { std::vector targetRowValues; std::vector conditionRowValues; uint64_t initialStateInSubmatrix; + bool isAcyclic; + std::unique_ptr> cachedSolver; + std::vector cachedX; + std::vector cachedB; }; enum class BisectionMethodBounds { Simple, Advanced }; @@ -538,10 +550,8 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper STORM_LOG_WARN_COND(!env.solver().isForceSoundness(), "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); - SolutionType const precision = [&env, boundOption]() { + SolutionType const precision = [&env]() { if (storm::NumberTraits::IsExact || env.solver().isForceExact()) { - STORM_LOG_WARN_COND(storm::NumberTraits::IsExact && boundOption == BisectionMethodBounds::Advanced, - "Selected bisection method with exact precision in a setting that might not terminate."); return storm::utility::zero(); } else { return storm::utility::convertNumber(env.solver().minMax().getPrecision()); @@ -559,12 +569,16 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b STORM_LOG_TRACE("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) << ",\n\t Upper bound: " << storm::utility::convertNumber(pMax)); } - storm::utility::Extremum lowerBound = storm::utility::zero(); - storm::utility::Extremum upperBound = storm::utility::one(); + storm::utility::Maximum lowerBound = storm::utility::zero(); + storm::utility::Minimum upperBound = storm::utility::one(); SolutionType middle = (*lowerBound + *upperBound) / 2; + [[maybe_unused]] SolutionType rationalCandiate = middle; // relevant for exact computations + [[maybe_unused]] uint64_t rationalCandidateCount = 0; + std::set checkedMiddleValues; // Middle values that have been checked already for (uint64_t iterationCount = 1; true; ++iterationCount) { // evaluate the current middle SolutionType const middleValue = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + checkedMiddleValues.insert(middle); // update the bounds and new middle value according to the bisection method if (boundOption == BisectionMethodBounds::Simple) { if (middleValue >= storm::utility::zero()) { @@ -584,7 +598,10 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b lowerBound &= middle + (middleValue / pMin); upperBound &= middle + (middleValue / pMax); } - // update middle to the average of the bounds, but scale it according to the middle value (which is in [-1,1]) + // update middle to the average of the bounds, but use the middleValue as a hint: + // If middleValue is close to -1, we use a value close to lowerBound + // If middleValue is close to 0, we use a value close to the avg(lowerBound, upperBound) + // If middleValue is close to +1, we use a value close to upperBound middle = *lowerBound + (storm::utility::one() + middleValue) * (*upperBound - *lowerBound) / 2; if (!storm::NumberTraits::IsExact && storm::utility::isAlmostZero(*upperBound - *lowerBound)) { @@ -617,22 +634,36 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b } // process the middle value for the next iteration if constexpr (storm::NumberTraits::IsExact) { - // find a rational number with a concise representation close to middle and within the bounds - auto const exactMiddle = middle; - - // Find number of digits - 1. Method using log10 does not work since that uses doubles internally. - auto numDigits = storm::utility::numDigits(*upperBound - *lowerBound) - 1; - - do { - ++numDigits; - middle = storm::utility::kwek_mehlhorn::sharpen(numDigits, exactMiddle); - } while (middle <= *lowerBound || middle >= *upperBound); + // Check if the rationalCandidate has been within the bounds for four iterations. + // If yes, we take that as our next "middle". + // Otherwise, we set a new rationalCandidate. + // This heuristic ensures that we eventually check every rational number without affecting the binary search too much + if (rationalCandidateCount >= 4 && rationalCandiate >= *lowerBound && rationalCandiate <= *upperBound && + !checkedMiddleValues.contains(rationalCandiate)) { + middle = rationalCandiate; + rationalCandidateCount = 0; + } else { + // find a rational number with a concise representation within our current bounds + bool const includeLower = !checkedMiddleValues.contains(*lowerBound); + bool const includeUpper = !checkedMiddleValues.contains(*upperBound); + auto newRationalCandiate = storm::utility::findRational(*lowerBound, includeLower, *upperBound, includeUpper); + if (rationalCandiate == newRationalCandiate) { + ++rationalCandidateCount; + } else { + rationalCandiate = newRationalCandiate; + rationalCandidateCount = 0; + } + // Also simplify the middle value + SolutionType delta = + std::min(*upperBound - middle, middle - *lowerBound) / storm::utility::convertNumber(16); + middle = storm::utility::findRational(middle - delta, true, middle + delta, true); + } } - // Since above code never sets 'middle' to exactly zero or one, we check if that could be necessary after a couple of iterations + // Since above code might never set 'middle' to exactly zero or one, we check if that could be necessary after a couple of iterations if (iterationCount == 8) { // 8 is just a heuristic value, it could be any number - if (storm::utility::isZero(*lowerBound)) { + if (storm::utility::isZero(*lowerBound) && !checkedMiddleValues.contains(storm::utility::zero())) { middle = storm::utility::zero(); - } else if (storm::utility::isOne(*upperBound)) { + } else if (storm::utility::isOne(*upperBound) && !checkedMiddleValues.contains(storm::utility::one())) { middle = storm::utility::one(); } } diff --git a/src/storm/utility/RationalApproximation.cpp b/src/storm/utility/RationalApproximation.cpp new file mode 100644 index 0000000000..c9fe407ed1 --- /dev/null +++ b/src/storm/utility/RationalApproximation.cpp @@ -0,0 +1,156 @@ + +#include "storm/utility/RationalApproximation.h" + +#include "storm/adapters/RationalNumberAdapter.h" +#include "storm/utility/constants.h" +#include "storm/utility/macros.h" + +namespace storm::utility { + +storm::RationalNumber findRational(storm::RationalNumber const& lowerBound, bool lowerInclusive, storm::RationalNumber const& upperBound, bool upperInclusive) { + using Integer = typename storm::NumberTraits::IntegerType; + STORM_LOG_ASSERT(lowerBound < upperBound || (lowerBound == upperBound && lowerInclusive && upperInclusive), "Invalid interval for rational approximation."); + + // Handle negative numbers + if (auto const zero = storm::utility::zero(); lowerBound < zero) { + // check if zero is in the interval + if (upperBound > zero || (upperBound == zero && upperInclusive)) { + return storm::utility::zero(); + } else { + // all numbers in the interval are negative. We translate that to a positive problem and negate the result + return -findRational(-upperBound, upperInclusive, -lowerBound, lowerInclusive); + } + } + // At this point, the solution is known to be non-negative + + // We compute a path in the Stern-Brocot tree from the root to the node representing the simplest rational in the closed interval [lowerBound, upperBound] + // If the input interval is open on one or both sides, we traverse the tree further down until a suitable rational number is found + // @see https://en.wikipedia.org/wiki/Stern–Brocot_tree#A_tree_of_continued_fractions + // @see https://mathoverflow.net/a/424509 + // The path is encoded using a simple continued fraction representation. + // We take path[0] times the right child, path[1] times the left child, path[2] times the right child, etc, using path.back()-1 steps in the last direction. + std::vector path; // in simple continued fraction representation + auto l = lowerBound; + auto u = upperBound; + while (true) { + auto l_den = storm::utility::denominator(l); + auto u_den = storm::utility::denominator(u); + auto const [l_i, l_rem] = storm::utility::divide(storm::utility::numerator(l), l_den); + auto const [u_i, u_rem] = storm::utility::divide(storm::utility::numerator(u), u_den); + + path.push_back(std::min(l_i, u_i)); // insert tree traversal information + if (l_i == u_i && !storm::utility::isZero(l_rem) && !storm::utility::isZero(u_rem)) { + // continue traversing the tree + l = storm::utility::convertNumber(l_den) / l_rem; + u = storm::utility::convertNumber(u_den) / u_rem; + continue; + } + // Reaching this point means that we have found a node in the Stern-Brocot tree where the paths for lower and upper bound diverge. + // If there still is a remainder, we need to add one to the last entry of the path so that it correctly encodes the node we are referring to. + if (l_i != u_i && !storm::utility::isZero(l_i < u_i ? l_rem : u_rem)) { + path.back() += Integer(1); + } + + // Find out if we hit an interval boundary and whether we need to adapt this due to open intervals + bool const needAdjustLower = !lowerInclusive && path.back() == l_i && storm::utility::isZero(l_rem); + bool const needAdjustUpper = !upperInclusive && path.back() == u_i && storm::utility::isZero(u_rem); + if (needAdjustLower || needAdjustUpper) { + // handle for values of the "other" bound that does not need adjustment + auto const& o_i = needAdjustLower ? u_i : l_i; + auto const& o_rem = needAdjustLower ? u_rem : l_rem; + auto const& o_den = needAdjustLower ? u_den : l_den; + auto const& o_inclusive = needAdjustLower ? upperInclusive : lowerInclusive; + + // When adjusting lower bounds, we need to explore the right subtree to obtain a larger value than the current lower bound + // When adjusting upper bounds, we need to explore the left subtree to obtain a smaller value than the current upper bound + // Whether we currently look at left or right subtrees is determined by the parity of the index in the path: + // Path entries at even indices correspond to right moves (increasing value) and entries at odd indices correspond to left moves (decreasing value) + bool const currentDirectionIsIncreasing = (path.size() - 1) % 2 == 0; + bool const adjustInCurrentDirection = (needAdjustLower && currentDirectionIsIncreasing) || (needAdjustUpper && !currentDirectionIsIncreasing); + // Below, we navigate through the Stern-Brocot tree by adapting the path + // path.back() += 1; extends the path to a child in the "current direction" + // path.back() -= 1; path.emplace_back(2); extends the path to a child in the "counter direction" + if (adjustInCurrentDirection) { + STORM_LOG_ASSERT(path.back() <= o_i, "Unexpected case when navigating the Stern-Brocot tree."); + if (path.back() + Integer(1) < o_i || (path.back() + Integer(1) == o_i && !storm::utility::isZero(o_rem))) { + // In this case, the next child (in the current direction) is inside the interval, so we can just take that + path.back() += Integer(1); + } else if (path.back() + Integer(1) == o_i && storm::utility::isZero(o_rem)) { + // In this case, the next child coincides with the other boundary + if (o_inclusive) { + path.back() += Integer(1); // add next child + } else { + // We first take one child in the current direction and then one child in the counter direction. + // path.back() += 1; path.back() -= 1; // cancels out + path.emplace_back(2); + } + } else { + // The following assertion holds because path.back() > o_i is not possible due to the way we constructed the path above + // and if there would be no remainder, the other boundary would be hit as well (i.e. we would have an empty interval (a,a). + STORM_LOG_ASSERT(path.back() == o_i && !storm::utility::isZero(o_rem), "Unexpected case when navigating the Stern-Brocot tree."); + // In this case, we need to append one child in the current direction and multiple children in the counter direction based on the continued + // fraction representation of the other boundary + auto const [o_i2, o_rem2] = storm::utility::divide(o_den, o_rem); + // path.back() += 1; path.back() -= 1; // cancels out + path.push_back(o_i2); + if (!storm::utility::isZero(o_rem2)) { + // If there still is a remainder, we add one to the last entry of the path so that it correctly encodes the node we are referring to. + path.back() += Integer(1); + } else if (!o_inclusive) { + // If there is no remainder, we are exactly on the other boundary. If that boundary is also excluded, we need to add one more step. + path.back() += Integer(1); + } + } + } else { + // Adjusting a bound in the counter direction can only happen if the other bound still has a remainder + // Otherwise, we would have also hit that bound + STORM_LOG_ASSERT(o_i == path.back() - Integer(1), "Unexpected case when navigating the Stern-Brocot tree."); + STORM_LOG_ASSERT(!storm::utility::isZero(o_rem), "Unexpected case when navigating the Stern-Brocot tree."); + auto const [o_i2, o_rem2] = storm::utility::divide(o_den, o_rem); + path.back() -= Integer(1); // necessary in all cases + if (o_i2 > Integer(2) || (o_i2 == Integer(2) && !storm::utility::isZero(o_rem2))) { + // In this case, the next child (in the counter direction) is inside the interval, so we can just take that + path.emplace_back(2); + } else if (o_i2 == Integer(2) && storm::utility::isZero(o_rem2)) { + // In this case, the next child in counter direction coincides with the other boundary + if (o_inclusive) { + path.emplace_back(2); + } else { + // We first take one child in the counter direction and then one child in the current direction. + path.emplace_back(1); + path.emplace_back(2); + } + } else { + STORM_LOG_ASSERT(o_i2 == Integer(1) && !storm::utility::isZero(o_rem2), "Unexpected case when navigating the Stern-Brocot tree."); + // In this case, we need to append one child in the counter direction and multiple children in the current direction based on the continued + // fraction representation of the other boundary + auto const [o_i3, o_rem3] = storm::utility::divide(o_rem, o_rem2); + path.emplace_back(1); + path.push_back(o_i3); + if (!storm::utility::isZero(o_rem3)) { + // If there still is a remainder, we add one to the last entry of the path so that it correctly encodes the node we are referring to. + path.back() += Integer(1); + } else if (!o_inclusive) { + // If there is no remainder, we are exactly on the other boundary. If that boundary is also excluded, we need to add one more step. + path.back() += Integer(1); + } + } + } + } + break; + } + + // Now, construct the rational number from the path + auto it = path.rbegin(); + auto result = storm::utility::convertNumber(*it); + for (++it; it != path.rend(); ++it) { + result = storm::utility::convertNumber(*it) + storm::utility::one() / result; + } + return result; + + STORM_LOG_ASSERT(result > lowerBound || lowerInclusive && result == lowerBound, "Result is below lower bound."); + STORM_LOG_ASSERT(result < upperBound || upperInclusive && result == upperBound, "Result is above upper bound."); + return result; +} + +} // namespace storm::utility \ No newline at end of file diff --git a/src/storm/utility/RationalApproximation.h b/src/storm/utility/RationalApproximation.h new file mode 100644 index 0000000000..17bae03928 --- /dev/null +++ b/src/storm/utility/RationalApproximation.h @@ -0,0 +1,18 @@ +#pragma once + +#include "storm/adapters/RationalNumberForward.h" + +namespace storm::utility { + +/*! + * Finds the "simplest" rational number in the given interval, where "simplest" means having the smallest denominator + * @pre lowerBound < upperBound or (lowerBound == upperBound and lowerInclusive and upperInclusive) + * @param lowerBound The lower bound of the interval + * @param lowerInclusive Whether the lower bound itself is included + * @param upperBound the upper bound of the interval + * @param upperInclusive Whether the upper bound itself is included + * @return the rational number in the given interval with the smallest denominator + */ +storm::RationalNumber findRational(storm::RationalNumber const& lowerBound, bool lowerInclusive, storm::RationalNumber const& upperBound, bool upperInclusive); + +} // namespace storm::utility \ No newline at end of file diff --git a/src/test/storm/utility/RationalApproximationTest.cpp b/src/test/storm/utility/RationalApproximationTest.cpp new file mode 100644 index 0000000000..9e7f770ee5 --- /dev/null +++ b/src/test/storm/utility/RationalApproximationTest.cpp @@ -0,0 +1,70 @@ +#include "storm-config.h" +#include "test/storm_gtest.h" + +#include "storm/adapters/RationalNumberAdapter.h" +#include "storm/utility/RationalApproximation.h" +#include "storm/utility/constants.h" + +namespace { + +storm::RationalNumber rn(double doubleValue) { + return storm::utility::convertNumber(doubleValue); +} + +storm::RationalNumber rn(std::string const& str) { + return storm::utility::convertNumber(str); +} +TEST(RationalApproximationTest, inclusive_bounds) { + EXPECT_EQ(rn("0"), storm::utility::findRational(rn("0"), true, rn("0"), true)); + EXPECT_EQ(rn("1"), storm::utility::findRational(rn("1"), true, rn("1"), true)); + EXPECT_EQ(rn("0"), storm::utility::findRational(rn("0"), true, rn("1"), true)); + EXPECT_EQ(rn("1/2"), storm::utility::findRational(rn("1/3"), true, rn("2/3"), true)); + EXPECT_EQ(rn("1/2"), storm::utility::findRational(rn("1/10"), true, rn("9/10"), true)); + EXPECT_EQ(rn("1"), storm::utility::findRational(rn("1/2"), true, rn("1"), true)); + EXPECT_EQ(rn("1"), storm::utility::findRational(rn("2/3"), true, rn("1"), true)); + EXPECT_EQ(rn("2/3"), storm::utility::findRational(rn("2/3"), true, rn("3/4"), true)); + EXPECT_EQ(rn("2/3"), storm::utility::findRational(rn("3/5"), true, rn("3/4"), true)); + EXPECT_EQ(rn("1"), storm::utility::findRational(rn("2/3"), true, rn("123456"), true)); + EXPECT_EQ(rn("23/3"), storm::utility::findRational(rn("23/3"), true, rn("31/4"), true)); + EXPECT_EQ(rn("23/3"), storm::utility::findRational(rn("38/5"), true, rn("31/4"), true)); + EXPECT_EQ(rn("75/7"), storm::utility::findRational(rn(10.71), true, rn(10.72), true)); + EXPECT_EQ(rn(0.123456), storm::utility::findRational(rn(0.123456), true, rn(0.123456), true)); + EXPECT_EQ(rn(987.123456), storm::utility::findRational(rn(987.123456), true, rn(987.123456), true)); +} + +TEST(RationalApproximationTest, exclusive_bounds) { + EXPECT_EQ(rn("1/2"), storm::utility::findRational(rn("0"), false, rn("1"), false)); + EXPECT_EQ(rn("0"), storm::utility::findRational(rn("0"), true, rn("1"), false)); + EXPECT_EQ(rn("1"), storm::utility::findRational(rn("0"), false, rn("1"), true)); + EXPECT_EQ(rn("1/3"), storm::utility::findRational(rn("0"), false, rn("1/2"), false)); + EXPECT_EQ(rn("2/3"), storm::utility::findRational(rn("1/2"), false, rn("1"), false)); + EXPECT_EQ(rn("3/4"), storm::utility::findRational(rn("2/3"), false, rn("1"), false)); + EXPECT_EQ(rn("5/7"), storm::utility::findRational(rn("2/3"), false, rn("3/4"), false)); + EXPECT_EQ(rn("3/2"), storm::utility::findRational(rn("1"), false, rn("2"), false)); + EXPECT_EQ(rn("30/19"), storm::utility::findRational(rn("11/7"), false, rn("19/12"), false)); + EXPECT_EQ(rn("11/7"), storm::utility::findRational(rn("11/7"), true, rn("19/12"), false)); + EXPECT_EQ(rn("19/12"), storm::utility::findRational(rn("11/7"), false, rn("19/12"), true)); + EXPECT_EQ(rn("1000/1001"), storm::utility::findRational(rn("999/1000"), false, rn("1"), false)); + EXPECT_EQ(rn("999/1000"), storm::utility::findRational(rn("999/1000"), true, rn("1"), false)); + EXPECT_EQ(rn("333/334"), storm::utility::findRational(rn("997/1000"), true, rn("1"), false)); + EXPECT_EQ(rn("1001/1000"), storm::utility::findRational(rn("1"), false, rn("1001/1000"), true)); + EXPECT_EQ(rn("1002/1001"), storm::utility::findRational(rn("1"), false, rn("1001/1000"), false)); + EXPECT_EQ(rn("335/334"), storm::utility::findRational(rn("1"), false, rn("1003/1000"), true)); + EXPECT_EQ(rn("500/1001"), storm::utility::findRational(rn("999/2000"), false, rn("1/2"), false)); + EXPECT_EQ(rn("167/335"), storm::utility::findRational(rn("997/2000"), true, rn("1/2"), false)); + EXPECT_EQ(rn("500/1001"), storm::utility::findRational(rn("500/1001"), true, rn("1/2"), false)); + EXPECT_EQ(rn("501/1001"), storm::utility::findRational(rn("1/2"), false, rn("501/1001"), true)); + EXPECT_EQ(rn("502/1003"), storm::utility::findRational(rn("1/2"), false, rn("501/1001"), false)); + EXPECT_EQ(rn("168/335"), storm::utility::findRational(rn("1/2"), false, rn("502/1001"), true)); +} + +TEST(RationalApproximationTest, negative) { + EXPECT_EQ(rn("0"), storm::utility::findRational(rn("-1"), false, rn("1"), false)); + EXPECT_EQ(rn("0"), storm::utility::findRational(rn("-1"), true, rn("0"), true)); + EXPECT_EQ(rn("-1"), storm::utility::findRational(rn("-1"), true, rn("0"), false)); + EXPECT_EQ(rn("-30/19"), storm::utility::findRational(rn("-19/12"), false, rn("-11/7"), false)); + EXPECT_EQ(rn("-11/7"), storm::utility::findRational(rn("-19/12"), false, rn("-11/7"), true)); + EXPECT_EQ(rn("-19/12"), storm::utility::findRational(rn("-19/12"), true, rn("-11/7"), false)); +} + +} // namespace From e547ac9735d98ece2655f02c2fdbd02d38b7a8f6 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 24 Dec 2025 11:51:12 +0100 Subject: [PATCH 080/102] Fix not (re-)setting the solver optimization direction --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index a23c5f4768..b97448d26e 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -441,13 +441,13 @@ class WeightedReachabilityHelper { } cachedSolver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(solverEnv, submatrix); cachedSolver->setCachingEnabled(true); - cachedSolver->setOptimizationDirection(dir); cachedSolver->setRequirementsChecked(); cachedSolver->setHasUniqueSolution(true); cachedSolver->setHasNoEndComponents(true); cachedSolver->setLowerBound(-storm::utility::one()); cachedSolver->setUpperBound(storm::utility::one()); } + cachedSolver->setOptimizationDirection(dir); // Initialize the right-hand side vector. createScaledVector(cachedB, targetWeight, targetRowValues, conditionWeight, conditionRowValues); @@ -526,9 +526,7 @@ class WeightedReachabilityHelper { std::vector const& v2) const { STORM_LOG_ASSERT(v1.size() == v2.size(), "Vector sizes must match"); out.resize(v1.size()); - for (size_t i = 0; i < v1.size(); ++i) { - out[i] = w1 * v1[i] + w2 * v2[i]; - } + storm::utility::vector::applyPointwise(v1, v2, out, [&w1, &w2](ValueType const& a, ValueType const& b) -> ValueType { return w1 * a + w2 * b; }); } storm::storage::SparseMatrix submatrix; From 018dc97182a1d76cc4a455c38516ceeed2df49eb Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Wed, 24 Dec 2025 11:53:32 +0100 Subject: [PATCH 081/102] Add missing brackets --- src/storm/utility/RationalApproximation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storm/utility/RationalApproximation.cpp b/src/storm/utility/RationalApproximation.cpp index c9fe407ed1..84700e5f76 100644 --- a/src/storm/utility/RationalApproximation.cpp +++ b/src/storm/utility/RationalApproximation.cpp @@ -148,8 +148,8 @@ storm::RationalNumber findRational(storm::RationalNumber const& lowerBound, bool } return result; - STORM_LOG_ASSERT(result > lowerBound || lowerInclusive && result == lowerBound, "Result is below lower bound."); - STORM_LOG_ASSERT(result < upperBound || upperInclusive && result == upperBound, "Result is above upper bound."); + STORM_LOG_ASSERT(result > lowerBound || (lowerInclusive && result == lowerBound), "Result is below lower bound."); + STORM_LOG_ASSERT(result < upperBound || (upperInclusive && result == upperBound), "Result is above upper bound."); return result; } From c244648084c22b19ccefa0b917c4f6f0c695d39d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 2 Jan 2026 12:16:49 +0100 Subject: [PATCH 082/102] fix compile problems --- .../region/SparseParameterLiftingModelChecker.cpp | 13 +++++++------ .../transformer/ObservationTraceUnfolder.cpp | 1 + .../helper/conditional/ConditionalHelper.cpp | 3 ++- src/storm/modelchecker/results/CheckResult.cpp | 1 + .../results/ExplicitQualitativeCheckResult.cpp | 3 +-- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp index 3c7a3dbe82..0cb3c6a252 100644 --- a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp @@ -101,15 +101,16 @@ RegionResult SparseParameterLiftingModelChecker:: (result == RegionResult::Unknown || result == RegionResult::ExistsIllDefined || result == RegionResult::CenterIllDefined)) { auto const center = region.region.getCenterPoint(); if (getInstantiationChecker(false).isWellDefined(center)) { - result = getInstantiationChecker(false).check(env, center)->asExplicitQualitativeCheckResult()[getUniqueInitialState()] + result = getInstantiationChecker(false).check(env, center)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()] ? RegionResult::CenterSat : RegionResult::CenterViolated; } else { auto const lowerCorner = region.region.getLowerBoundaries(); if (getInstantiationChecker(false).isWellDefined(lowerCorner)) { - result = getInstantiationChecker(false).check(env, lowerCorner)->asExplicitQualitativeCheckResult()[getUniqueInitialState()] - ? RegionResult::ExistsSat - : RegionResult::ExistsViolated; + result = + getInstantiationChecker(false).check(env, lowerCorner)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()] + ? RegionResult::ExistsSat + : RegionResult::ExistsViolated; } else { result = RegionResult::CenterIllDefined; } @@ -143,7 +144,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto const valuation = getOptimalValuationForMonotonicity(region.region, globalMonotonicity->getMonotonicityResult(), dirToCheck); STORM_LOG_ASSERT(valuation.size() == region.region.getVariables().size(), "Not all parameters seem to be monotonic."); auto& checker = existsSat ? getInstantiationCheckerSAT(false) : getInstantiationCheckerVIO(false); - bool const monCheckResult = checker.check(env, valuation)->asExplicitQualitativeCheckResult()[getUniqueInitialState()]; + bool const monCheckResult = checker.check(env, valuation)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]; if (existsSat == monCheckResult) { result = existsSat ? RegionResult::AllSat : RegionResult::AllViolated; STORM_LOG_INFO("Region " << region.region << " is " << result << ", discovered with instantiation checker on " << valuation @@ -165,7 +166,7 @@ RegionResult SparseParameterLiftingModelChecker:: // Try to prove AllSat or AllViolated through parameterLifting auto const checkResult = this->check(env, region, dirToCheck); if (checkResult) { - bool const value = checkResult->asExplicitQualitativeCheckResult()[getUniqueInitialState()]; + bool const value = checkResult->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]; if ((dirToCheck == dirForSat) == value) { result = (dirToCheck == dirForSat) ? RegionResult::AllSat : RegionResult::AllViolated; } else if (sampleVerticesOfRegion) { diff --git a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp index b687e1d5ea..fabf264914 100644 --- a/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp +++ b/src/storm-pomdp/transformer/ObservationTraceUnfolder.cpp @@ -1,5 +1,6 @@ #include "storm-pomdp/transformer/ObservationTraceUnfolder.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidArgumentException.h" #include "storm/storage/expressions/ExpressionManager.h" diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 8aab7ef461..ec281fa465 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -1,6 +1,7 @@ #include "storm/modelchecker/helper/conditional/ConditionalHelper.h" #include +#include #include "storm/adapters/RationalNumberAdapter.h" #include "storm/environment/modelchecker/ModelCheckerEnvironment.h" @@ -813,7 +814,7 @@ class WeightedReachabilityHelper { } internal::SolverResult computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, - ValueType const& conditionWeight, bool computeScheduler) const { + ValueType const& conditionWeight, bool computeScheduler) { // Set up the solver. if (!cachedSolver) { auto solverEnv = env; diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 0bdd406f21..f6c6827c0b 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -1,5 +1,6 @@ #include "storm/modelchecker/results/CheckResult.h" +#include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/modelchecker/results/ExplicitParetoCurveCheckResult.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 1ca56bc279..8cf38d995e 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -2,6 +2,7 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/JsonAdapter.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" @@ -337,7 +338,6 @@ template class ExplicitQualitativeCheckResult; template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, std::optional const&) const; -#ifdef STORM_HAVE_CARL template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; @@ -358,7 +358,6 @@ template storm::json ExplicitQualitativeCheckResult::to std::optional const&) const; template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; -#endif } // namespace modelchecker } // namespace storm From ee84da595d0887fbbed38cde82fdb5f794b677c4 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sat, 10 Jan 2026 01:12:03 +0100 Subject: [PATCH 083/102] conditional bisection: Integrated policy tracking approach --- .../ConditionalAlgorithmSetting.cpp | 8 ++ .../conditional/ConditionalAlgorithmSetting.h | 10 +- .../helper/conditional/ConditionalHelper.cpp | 123 +++++++++++++----- .../settings/modules/ModelCheckerSettings.cpp | 2 +- .../ConditionalMdpPrctlModelCheckerTest.cpp | 53 +++++++- 5 files changed, 160 insertions(+), 36 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.cpp b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.cpp index e909df6278..5837a7a727 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.cpp @@ -11,6 +11,10 @@ std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithmSetting const return stream << "bisection"; case ConditionalAlgorithmSetting::BisectionAdvanced: return stream << "bisection-advanced"; + case ConditionalAlgorithmSetting::BisectionPolicyTracking: + return stream << "bisection-pt"; + case ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking: + return stream << "bisection-advanced-pt"; case ConditionalAlgorithmSetting::PolicyIteration: return stream << "pi"; } @@ -27,6 +31,10 @@ ConditionalAlgorithmSetting conditionalAlgorithmSettingFromString(std::string co return ConditionalAlgorithmSetting::Bisection; } else if (algorithm == "bisection-advanced") { return ConditionalAlgorithmSetting::BisectionAdvanced; + } else if (algorithm == "bisection-pt") { + return ConditionalAlgorithmSetting::BisectionPolicyTracking; + } else if (algorithm == "bisection-advanced-pt") { + return ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking; } else if (algorithm == "pi") { return ConditionalAlgorithmSetting::PolicyIteration; } diff --git a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h index 4a9440abb4..6c77495af9 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h +++ b/src/storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h @@ -5,7 +5,15 @@ #include "storm/utility/macros.h" namespace storm { -enum class ConditionalAlgorithmSetting { Default, Restart, Bisection, BisectionAdvanced, PolicyIteration }; +enum class ConditionalAlgorithmSetting { + Default, + Restart, + Bisection, + BisectionAdvanced, + BisectionPolicyTracking, + BisectionAdvancedPolicyTracking, + PolicyIteration +}; std::ostream& operator<<(std::ostream& stream, ConditionalAlgorithmSetting const& algorithm); ConditionalAlgorithmSetting conditionalAlgorithmSettingFromString(std::string const& algorithm); diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index b97448d26e..5231bea762 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -15,6 +15,7 @@ #include "storm/storage/SparseMatrix.h" #include "storm/transformer/EndComponentEliminator.h" #include "storm/utility/Extremum.h" +#include "storm/utility/OptionalRef.h" #include "storm/utility/RationalApproximation.h" #include "storm/utility/SignalHandler.h" #include "storm/utility/graph.h" @@ -431,7 +432,7 @@ class WeightedReachabilityHelper { } SolutionType computeWeightedDiff(storm::Environment const& env, storm::OptimizationDirection const dir, ValueType const& targetWeight, - ValueType const& conditionWeight) { + ValueType const& conditionWeight, storm::OptionalRef> schedulerOutput = {}) { // Set up the solver. if (!cachedSolver) { auto solverEnv = env; @@ -447,6 +448,7 @@ class WeightedReachabilityHelper { cachedSolver->setLowerBound(-storm::utility::one()); cachedSolver->setUpperBound(storm::utility::one()); } + cachedSolver->setTrackScheduler(schedulerOutput.has_value()); cachedSolver->setOptimizationDirection(dir); // Initialize the right-hand side vector. @@ -456,6 +458,9 @@ class WeightedReachabilityHelper { cachedX.assign(submatrix.getRowGroupCount(), storm::utility::zero()); cachedSolver->solveEquations(env, cachedX, cachedB); + if (schedulerOutput) { + *schedulerOutput = cachedSolver->getSchedulerChoices(); + } return cachedX[initialStateInSubmatrix]; } @@ -464,7 +469,7 @@ class WeightedReachabilityHelper { } void evaluateScheduler(storm::Environment const& env, std::vector& scheduler, std::vector& targetResults, - std::vector& conditionResults) const { + std::vector& conditionResults) { if (scheduler.empty()) { scheduler.resize(submatrix.getRowGroupCount(), 0); } @@ -474,23 +479,31 @@ class WeightedReachabilityHelper { if (conditionResults.empty()) { conditionResults.resize(submatrix.getRowGroupCount(), storm::utility::zero()); } - // apply the scheduler - storm::solver::GeneralLinearEquationSolverFactory factory; - bool const convertToEquationSystem = factory.getEquationProblemFormat(env) == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; - auto scheduledMatrix = submatrix.selectRowsFromRowGroups(scheduler, convertToEquationSystem); - if (convertToEquationSystem) { - scheduledMatrix.convertToEquationSystem(); - } - auto solver = factory.create(env, std::move(scheduledMatrix)); - solver->setBounds(storm::utility::zero(), storm::utility::one()); - solver->setCachingEnabled(true); + auto solver = getScheduledSolver(env, scheduler); - std::vector subB(submatrix.getRowGroupCount()); - storm::utility::vector::selectVectorValues(subB, scheduler, submatrix.getRowGroupIndices(), targetRowValues); - solver->solveEquations(env, targetResults, subB); + cachedB.resize(submatrix.getRowGroupCount()); + storm::utility::vector::selectVectorValues(cachedB, scheduler, submatrix.getRowGroupIndices(), targetRowValues); + solver->solveEquations(env, targetResults, cachedB); - storm::utility::vector::selectVectorValues(subB, scheduler, submatrix.getRowGroupIndices(), conditionRowValues); - solver->solveEquations(env, conditionResults, subB); + storm::utility::vector::selectVectorValues(cachedB, scheduler, submatrix.getRowGroupIndices(), conditionRowValues); + solver->solveEquations(env, conditionResults, cachedB); + } + + SolutionType evaluateScheduler(storm::Environment const& env, std::vector const& scheduler) { + STORM_LOG_ASSERT(scheduler.size() == submatrix.getRowGroupCount(), "Scheduler size does not match number of row groups"); + auto solver = getScheduledSolver(env, scheduler); + cachedB.resize(submatrix.getRowGroupCount()); + cachedX.resize(submatrix.getRowGroupCount()); + + storm::utility::vector::selectVectorValues(cachedB, scheduler, submatrix.getRowGroupIndices(), targetRowValues); + solver->solveEquations(env, cachedX, cachedB); + SolutionType targetValue = cachedX[initialStateInSubmatrix]; + + storm::utility::vector::selectVectorValues(cachedB, scheduler, submatrix.getRowGroupIndices(), conditionRowValues); + solver->solveEquations(env, cachedX, cachedB); + SolutionType ConditionValue = cachedX[initialStateInSubmatrix]; + + return targetValue / ConditionValue; } template @@ -529,6 +542,20 @@ class WeightedReachabilityHelper { storm::utility::vector::applyPointwise(v1, v2, out, [&w1, &w2](ValueType const& a, ValueType const& b) -> ValueType { return w1 * a + w2 * b; }); } + auto getScheduledSolver(storm::Environment const& env, std::vector const& scheduler) const { + // apply the scheduler + storm::solver::GeneralLinearEquationSolverFactory factory; + bool const convertToEquationSystem = factory.getEquationProblemFormat(env) == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; + auto scheduledMatrix = submatrix.selectRowsFromRowGroups(scheduler, convertToEquationSystem); + if (convertToEquationSystem) { + scheduledMatrix.convertToEquationSystem(); + } + auto solver = factory.create(env, std::move(scheduledMatrix)); + solver->setBounds(storm::utility::zero(), storm::utility::one()); + solver->setCachingEnabled(true); + return solver; + } + storm::storage::SparseMatrix submatrix; storm::storage::BitVector rowsWithSum1; std::vector targetRowValues; @@ -540,9 +567,8 @@ class WeightedReachabilityHelper { std::vector cachedB; }; -enum class BisectionMethodBounds { Simple, Advanced }; template -SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds boundOption, uint64_t const initialState, +SolutionType computeViaBisection(Environment const& env, bool const useAdvancedBounds, bool const usePolicyTracking, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper @@ -561,7 +587,7 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b SolutionType pMin{storm::utility::zero()}; SolutionType pMax{storm::utility::one()}; - if (boundOption == BisectionMethodBounds::Advanced) { + if (useAdvancedBounds) { pMin = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Minimize, storm::utility::zero(), storm::utility::one()); pMax = wrh.computeWeightedDiff(env, storm::OptimizationDirection::Maximize, storm::utility::zero(), storm::utility::one()); STORM_LOG_TRACE("Conditioning event bounds:\n\t Lower bound: " << storm::utility::convertNumber(pMin) @@ -569,32 +595,49 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b } storm::utility::Maximum lowerBound = storm::utility::zero(); storm::utility::Minimum upperBound = storm::utility::one(); + + std::optional> lowerScheduler, upperScheduler, middleScheduler; + storm::OptionalRef> middleSchedulerRef; + if (usePolicyTracking) { + lowerScheduler.emplace(); + upperScheduler.emplace(); + middleScheduler.emplace(); + middleSchedulerRef.reset(*middleScheduler); + } + SolutionType middle = (*lowerBound + *upperBound) / 2; [[maybe_unused]] SolutionType rationalCandiate = middle; // relevant for exact computations [[maybe_unused]] uint64_t rationalCandidateCount = 0; std::set checkedMiddleValues; // Middle values that have been checked already for (uint64_t iterationCount = 1; true; ++iterationCount) { // evaluate the current middle - SolutionType const middleValue = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle); + SolutionType const middleValue = wrh.computeWeightedDiff(env, dir, storm::utility::one(), -middle, middleSchedulerRef); checkedMiddleValues.insert(middle); // update the bounds and new middle value according to the bisection method - if (boundOption == BisectionMethodBounds::Simple) { + if (!useAdvancedBounds) { if (middleValue >= storm::utility::zero()) { - lowerBound &= middle; + if (lowerBound &= middle) { + lowerScheduler.swap(middleScheduler); + } } if (middleValue <= storm::utility::zero()) { - upperBound &= middle; + if (upperBound &= middle) { + upperScheduler.swap(middleScheduler); + } } middle = (*lowerBound + *upperBound) / 2; // update middle to the average of the bounds } else { - STORM_LOG_ASSERT(boundOption == BisectionMethodBounds::Advanced, "Unknown bisection method bounds"); if (middleValue >= storm::utility::zero()) { - lowerBound &= middle + (middleValue / pMax); + if (lowerBound &= middle + (middleValue / pMax)) { + lowerScheduler.swap(middleScheduler); + } upperBound &= middle + (middleValue / pMin); } if (middleValue <= storm::utility::zero()) { lowerBound &= middle + (middleValue / pMin); - upperBound &= middle + (middleValue / pMax); + if (upperBound &= middle + (middleValue / pMax)) { + upperScheduler.swap(middleScheduler); + } } // update middle to the average of the bounds, but use the middleValue as a hint: // If middleValue is close to -1, we use a value close to lowerBound @@ -623,6 +666,12 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b << std::setprecision(std::numeric_limits::digits10) << storm::utility::convertNumber(boundDiff) << "."); break; + } else if (usePolicyTracking && lowerScheduler && upperScheduler && (*lowerScheduler == *upperScheduler)) { + STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations due to identical schedulers for lower and upper bound."); + auto result = wrh.evaluateScheduler(env, *lowerScheduler); + lowerBound &= result; + upperBound &= result; + break; } // check for early termination if (storm::utility::resources::isTerminate()) { @@ -669,6 +718,18 @@ SolutionType computeViaBisection(Environment const& env, BisectionMethodBounds b return (*lowerBound + *upperBound) / 2; } +template +SolutionType computeViaBisection(Environment const& env, ConditionalAlgorithmSetting const alg, uint64_t const initialState, + storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, + NormalFormData const& normalForm) { + using enum ConditionalAlgorithmSetting; + STORM_LOG_ASSERT(alg == Bisection || alg == BisectionAdvanced || alg == BisectionPolicyTracking || alg == BisectionAdvancedPolicyTracking, + "Unhandled Bisection algorithm " << alg << "."); + bool const useAdvancedBounds = (alg == BisectionAdvanced || alg == BisectionAdvancedPolicyTracking); + bool const usePolicyTracking = (alg == BisectionPolicyTracking || alg == BisectionAdvancedPolicyTracking); + return computeViaBisection(env, useAdvancedBounds, usePolicyTracking, initialState, dir, transitionMatrix, normalForm); +} + template SolutionType computeViaPolicyIteration(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { @@ -777,12 +838,10 @@ std::unique_ptr computeConditionalProbabilities(Environment const& initialStateValue = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); break; case ConditionalAlgorithmSetting::Bisection: - initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Simple, initialState, goal.direction(), - transitionMatrix, normalFormData); - break; case ConditionalAlgorithmSetting::BisectionAdvanced: - initialStateValue = internal::computeViaBisection(analysisEnv, internal::BisectionMethodBounds::Advanced, initialState, goal.direction(), - transitionMatrix, normalFormData); + case ConditionalAlgorithmSetting::BisectionPolicyTracking: + case ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking: + initialStateValue = internal::computeViaBisection(analysisEnv, alg, initialState, goal.direction(), transitionMatrix, normalFormData); break; case ConditionalAlgorithmSetting::PolicyIteration: initialStateValue = internal::computeViaPolicyIteration(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index 7806c9abc7..4689ee7802 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -26,7 +26,7 @@ ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { .build()) .build()); - std::vector const conditionalAlgs = {"default", "restart", "bisection", "bisection-advanced", "pi"}; + std::vector const conditionalAlgs = {"default", "restart", "bisection", "bisection-advanced", "bisection-pt", "bisection-advanced-pt", "pi"}; this->addOption(storm::settings::OptionBuilder(moduleName, conditionalAlgorithmOptionName, false, "The used algorithm for conditional probabilities.") .setIsAdvanced() .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the method to use.") diff --git a/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp index 1f9f41cbe8..597a78bfee 100644 --- a/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp @@ -49,6 +49,30 @@ class SparseDoubleBisectionAdvancedEnvironment { } }; +class SparseDoubleBisectionPtEnvironment { + public: + static const bool isExact = false; + typedef double ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionPolicyTracking); + return env; + } +}; + +class SparseDoubleBisectionAdvancedPtEnvironment { + public: + static const bool isExact = false; + typedef double ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking); + return env; + } +}; + class SparseDoublePiEnvironment { public: static const bool isExact = false; @@ -98,6 +122,30 @@ class SparseRationalNumberBisectionAdvancedEnvironment { } }; +class SparseRationalNumberBisectionPtEnvironment { + public: + static const bool isExact = true; + typedef storm::RationalNumber ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionPolicyTracking); + return env; + } +}; + +class SparseRationalNumberBisectionAdvancedPtEnvironment { + public: + static const bool isExact = true; + typedef storm::RationalNumber ValueType; + typedef storm::models::sparse::Mdp ModelType; + static storm::Environment createEnvironment() { + storm::Environment env; + env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking); + return env; + } +}; + class SparseRationalNumberPiEnvironment { public: static const bool isExact = true; @@ -159,9 +207,10 @@ class ConditionalMdpPrctlModelCheckerTest : public ::testing::Test { storm::Environment _environment; }; -typedef ::testing::Types + SparseRationalNumberBisectionPtEnvironment, SparseRationalNumberBisectionAdvancedPtEnvironment, SparseRationalNumberPiEnvironment> TestingTypes; TYPED_TEST_SUITE(ConditionalMdpPrctlModelCheckerTest, TestingTypes, ); From 45ea7eddc2d19db21b02cfc5646029b456a012a1 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Thu, 15 Jan 2026 15:34:49 +0100 Subject: [PATCH 084/102] cleaner scheduler computation --- .../helper/conditional/ConditionalHelper.cpp | 510 +++++++++--------- .../MaximalEndComponentDecomposition.cpp | 2 + 2 files changed, 256 insertions(+), 256 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index a09d21246e..7e8adfab7a 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -30,8 +30,8 @@ namespace internal { template std::optional::EndComponentEliminatorReturnType> eliminateEndComponents( - storm::storage::BitVector possibleEcStates, bool addRowAtRepresentativeState, std::optional representativeRowEntry, - storm::storage::SparseMatrix& matrix, uint64_t& initialState, storm::storage::BitVector& rowsWithSum1, std::vector& rowValues1, + storm::storage::BitVector const& possibleEcStates, bool addRowAtRepresentativeState, std::optional const representativeRowEntry, + storm::storage::SparseMatrix& matrix, storm::storage::BitVector& rowsWithSum1, std::vector& rowValues1, storm::OptionalRef> rowValues2 = {}) { storm::storage::MaximalEndComponentDecomposition ecs(matrix, matrix.transpose(true), possibleEcStates, rowsWithSum1); if (ecs.empty()) { @@ -71,9 +71,6 @@ std::optional::En updateRowValue(*rowValues2); } - // update initial state - initialState = ecElimResult.oldToNewStateMapping[initialState]; - // update bitvector storm::storage::BitVector newRowsWithSum1(ecElimResult.newToOldRowMapping.size(), true); uint64_t newRowIndex = 0; @@ -90,9 +87,9 @@ std::optional::En template SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, - std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, - storm::solver::OptimizationDirection const dir, uint64_t const initialState, - storm::OptionalRef> schedulerOutput = {}) { + std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, + storm::solver::OptimizationDirection const dir, uint64_t const initialState, + std::optional>& schedulerOutput) { // Initialize the solution vector. std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); @@ -127,7 +124,7 @@ std::unique_ptr> computeReachabilityProbabi storm::storage::BitVector const& allowedStates, storm::storage::BitVector const& targetStates, bool computeScheduler = true) { std::unique_ptr> scheduler; if (computeScheduler) { - scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); } if (initialStates.empty()) { // nothing to do @@ -155,11 +152,11 @@ std::unique_ptr> computeReachabilityProbabi } if (computeScheduler) { - auto submatrixIdx = 0; - for (auto state : reachableStates) { - scheduler->setChoice(subResult.scheduler->getChoice(submatrixIdx), state); - ++submatrixIdx; - } + auto submatrixIdx = 0; + for (auto state : reachableStates) { + scheduler->setChoice(subResult.scheduler->getChoice(submatrixIdx), state); + ++submatrixIdx; + } } return scheduler; @@ -317,9 +314,6 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc } } - // TODO: avoid this - auto const transposedMatrixWithGroups = transitionMatrix.transpose(false); - // dfs to find which choices in initial component states lead to condOrTargetStates storm::storage::BitVector choicesThatCanVisitCondOrTargetStates(transitionMatrix.getRowCount(), false); std::stack toProcess; @@ -330,22 +324,21 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc while (!toProcess.empty()) { auto currentState = toProcess.top(); toProcess.pop(); - for (auto const& entry : transposedMatrixWithGroups.getRow(currentState)) { - auto predecessorChoiceIndex = entry.getColumn(); - if (!allowedChoices.get(predecessorChoiceIndex) || choicesThatCanVisitCondOrTargetStates.get(predecessorChoiceIndex)) { - continue; - } - choicesThatCanVisitCondOrTargetStates.set(predecessorChoiceIndex, true); - uint64_t predecessorState = 0; - for (uint64_t state = 0; state < rowGroupCount; ++state) { - if (predecessorChoiceIndex < rowGroups[state + 1]) { - predecessorState = state; - break; + for (auto const& entry : backwardTransitions.getRow(currentState)) { + uint64_t const predecessorState = entry.getColumn(); + for (uint64_t const predecessorChoice : transitionMatrix.getRowGroupIndices(predecessorState)) { + if (!allowedChoices.get(predecessorChoice) || choicesThatCanVisitCondOrTargetStates.get(predecessorChoice)) { + continue; // The choice is either not allowed or has been considered already + } + if (auto const r = transitionMatrix.getRow(predecessorChoice); + std::none_of(r.begin(), r.end(), [¤tState](auto const& e) { return e.getColumn() == currentState; })) { + continue; // not an actual predecessor choice + } + choicesThatCanVisitCondOrTargetStates.set(predecessorChoice, true); + if (!visitedStates.get(predecessorState)) { + visitedStates.set(predecessorState, true); + toProcess.push(predecessorState); } - } - if (!visitedStates.get(predecessorState)) { - visitedStates.set(predecessorState, true); - toProcess.push(predecessorState); } } } @@ -356,34 +349,23 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc storm::storage::BitVector choicesAllowedForInitialComponent = allowedChoices & ~disallowedInitialComponentExits; storm::storage::BitVector goodInitialComponentStates = initialComponentStates; - storm::storage::BitVector goodInitialComponentStatesFixpoint = initialComponentStates; for (auto state : initialComponentExitStates) { - bool allChoicesAreDisallowed = true; - for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { - if (!disallowedInitialComponentExits.get(choiceIndex)) { - allChoicesAreDisallowed = false; - break; - } - } + auto const groupStart = transitionMatrix.getRowGroupIndices()[state]; + auto const groupEnd = transitionMatrix.getRowGroupIndices()[state + 1]; + bool const allChoicesAreDisallowed = disallowedInitialComponentExits.getNextUnsetIndex(groupStart) >= groupEnd; if (allChoicesAreDisallowed) { goodInitialComponentStates.set(state, false); } } - - // TODO while(progress) - while (goodInitialComponentStates.getNumberOfSetBits() != goodInitialComponentStatesFixpoint.getNumberOfSetBits()) { - goodInitialComponentStatesFixpoint = goodInitialComponentStates; + bool progress = true; + while (progress) { + progress = false; for (auto state : goodInitialComponentStates) { bool allChoicesAreDisallowed = true; for (auto choiceIndex : transitionMatrix.getRowGroupIndices(state)) { - bool hasBadSuccessor = false; - for (auto const& entry : transitionMatrix.getRow(choiceIndex)) { - auto targetState = entry.getColumn(); - if (!goodInitialComponentStates.get(targetState)) { - hasBadSuccessor = true; - break; - } - } + auto row = transitionMatrix.getRow(choiceIndex); + bool const hasBadSuccessor = std::any_of( + row.begin(), row.end(), [&goodInitialComponentStates](auto const& entry) { return !goodInitialComponentStates.get(entry.getColumn()); }); if (hasBadSuccessor) { choicesAllowedForInitialComponent.set(choiceIndex, false); } else { @@ -392,6 +374,7 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc } if (allChoicesAreDisallowed) { goodInitialComponentStates.set(state, false); + progress = true; } } } @@ -442,7 +425,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { auto const& maybeStates = normalForm.maybeStates; - auto const stateToMatrixIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); + auto originalToReducedStateIndexMap = maybeStates.getNumberOfSetBitsBeforeIndices(); auto const numMaybeStates = maybeStates.getNumberOfSetBits(); auto const numMaybeChoices = transitionMatrix.getNumRowsInRowGroups(maybeStates); @@ -484,139 +467,144 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme // Insert backloop probability if we haven't done so yet and are past the initial state index // This is to avoid a costly out-of-order insertion into the matrix if (addRestartTransition && entry.getColumn() > initialState) { - matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[initialState], restartProbability); + matrixBuilder.addNextValue(currentRow, originalToReducedStateIndexMap[initialState], restartProbability); addRestartTransition = false; } if (maybeStates.get(entry.getColumn())) { - matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[entry.getColumn()], entry.getValue()); + matrixBuilder.addNextValue(currentRow, originalToReducedStateIndexMap[entry.getColumn()], entry.getValue()); } } // Add the backloop if we haven't done this already if (addRestartTransition) { - matrixBuilder.addNextValue(currentRow, stateToMatrixIndexMap[initialState], restartProbability); + matrixBuilder.addNextValue(currentRow, originalToReducedStateIndexMap[initialState], restartProbability); } ++currentRow; } } + STORM_LOG_ASSERT(currentRow == numMaybeChoices, "Unexpected number of constructed rows."); - // TODO: why copy - auto maybeMatrix = matrixBuilder.build(); - auto matrix = storm::storage::SparseMatrix(maybeMatrix); - auto initStateInMatrix = stateToMatrixIndexMap[initialState]; + auto matrix = matrixBuilder.build(); + auto initStateInReduced = originalToReducedStateIndexMap[initialState]; // Eliminate end components in two phases // First, we catch all end components that do not contain the initial state. It is possible to stay in those ECs forever // without reaching the condition. This is reflected by a backloop to the initial state. - storm::storage::BitVector selectedStatesInMatrix(numMaybeStates, true); - selectedStatesInMatrix.set(initStateInMatrix, false); - auto ecElimResult1 = eliminateEndComponents(selectedStatesInMatrix, true, initStateInMatrix, matrix, initStateInMatrix, rowsWithSum1, rowValues); + storm::storage::BitVector selectedStatesInReduced(numMaybeStates, true); + selectedStatesInReduced.set(initStateInReduced, false); + auto ecElimResult1 = eliminateEndComponents(selectedStatesInReduced, true, initStateInReduced, matrix, rowsWithSum1, rowValues); + selectedStatesInReduced.set(initStateInReduced, true); + if (ecElimResult1) { + selectedStatesInReduced.resize(matrix.getRowGroupCount(), true); + initStateInReduced = ecElimResult1->oldToNewStateMapping[initStateInReduced]; + } // Second, eliminate the remaining ECs. These must involve the initial state and might have been introduced in the previous step. // A policy selecting such an EC must reach the condition with probability zero and is thus invalid. - selectedStatesInMatrix.set(initStateInMatrix, true); - auto ecElimResult2 = eliminateEndComponents(selectedStatesInMatrix, false, std::nullopt, matrix, initStateInMatrix, rowsWithSum1, rowValues); + auto ecElimResult2 = eliminateEndComponents(selectedStatesInReduced, false, std::nullopt, matrix, rowsWithSum1, rowValues); + if (ecElimResult2) { + initStateInReduced = ecElimResult2->oldToNewStateMapping[initStateInReduced]; + } STORM_LOG_INFO("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " << matrix.getEntryCount() << " transitions."); - // Finally, solve the equation system - auto result = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInMatrix, computeScheduler); - storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); - storm::storage::BitVector initialComponentExitStates(transitionMatrix.getRowGroupCount(), false); - for (auto rowIndex : matrix.getRowGroupIndices(initStateInMatrix)) { - uint64_t originalRowIndex = rowIndex; - if (ecElimResult2.has_value()) { - originalRowIndex = ecElimResult2->newToOldRowMapping[originalRowIndex]; - } - if (ecElimResult1.has_value()) { - originalRowIndex = ecElimResult1->newToOldRowMapping[originalRowIndex]; - } + // Finally, solve the equation system, potentially computing a scheduler + std::optional> reducedSchedulerChoices; + if (computeScheduler) { + reducedSchedulerChoices.emplace(); + } + auto resultValue = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInReduced, reducedSchedulerChoices); - uint64_t originalState; - uint64_t originalChoice; - auto const rowGroups = maybeMatrix.getRowGroupIndices(); - for (originalState = 0; originalState < maybeMatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState + 1]; - if (firstRowStateIndex > originalRowIndex) { - originalChoice = originalRowIndex - rowGroups[originalState]; - break; - } - } + // Create result (scheduler potentially added below) + auto finalResult = ResultReturnType(resultValue); - uint64_t index = maybeStates.getNextSetIndex(0); - for (uint64_t s = 0; s < originalState; ++s) { - index = maybeStates.getNextSetIndex(index + 1); + if (!computeScheduler) { + return finalResult; + } + // At this point we have to reconstruct the scheduler for the original model + STORM_LOG_ASSERT(reducedSchedulerChoices.has_value() && reducedSchedulerChoices->size() == matrix.getRowGroupCount(), + "Requested scheduler, but it was not computed or has invalid size."); + // For easier access, we create and update some index mappings + std::vector originalRowToStateIndexMap; // maps original row indices to original state indices. transitionMatrix.getRowGroupIndices() are the + // inverse of that mapping + originalRowToStateIndexMap.reserve(transitionMatrix.getRowCount()); + for (uint64_t originalStateIndex = 0; originalStateIndex < transitionMatrix.getRowGroupCount(); ++originalStateIndex) { + originalRowToStateIndexMap.insert(originalRowToStateIndexMap.end(), transitionMatrix.getRowGroupSize(originalStateIndex), originalStateIndex); + } + std::vector reducedToOriginalRowIndexMap; // maps row indices of the reduced model to the original ones + reducedToOriginalRowIndexMap.reserve(numMaybeChoices); + for (uint64_t const originalMaybeState : maybeStates) { + for (auto const originalRowIndex : transitionMatrix.getRowGroupIndices(originalMaybeState)) { + reducedToOriginalRowIndexMap.push_back(originalRowIndex); } - - originalState = index; - - initialComponentExitRows.set(transitionMatrix.getRowGroupIndices()[originalState] + originalChoice, true); - initialComponentExitStates.set(originalState, true); } - - // Create result without scheduler - auto finalResult = ResultReturnType(result.initialStateValue); - - // If requested, construct the scheduler for the original model - if (computeScheduler && result.hasScheduler()) { - storm::storage::BitVector maybeStatesWithChoice(maybeStates.size(), false); - std::unique_ptr> scheduler; - uint64_t chosenInitialComponentExitState; - uint64_t chosenInitialComponentExit; - scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); - - uint64_t state = 0; - for (auto& choice : *result.scheduler) { - uint64_t firstRowIndex = matrix.getRowGroupIndices()[state]; - uint64_t originalChoice = firstRowIndex + choice; + if (ecElimResult1.has_value() || ecElimResult2.has_value()) { + // reducedToOriginalRowIndexMap needs to be updated so it maps from rows of the ec-eliminated system + std::vector tmpReducedToOriginalRowIndexMap; + tmpReducedToOriginalRowIndexMap.reserve(matrix.getRowCount()); + for (uint64_t reducedRow = 0; reducedRow < matrix.getRowCount(); ++reducedRow) { + uint64_t intermediateRow = reducedRow; if (ecElimResult2.has_value()) { - originalChoice = ecElimResult2->newToOldRowMapping[originalChoice]; + intermediateRow = ecElimResult2->newToOldRowMapping.at(intermediateRow); } if (ecElimResult1.has_value()) { - originalChoice = ecElimResult1->newToOldRowMapping[originalChoice]; + intermediateRow = ecElimResult1->newToOldRowMapping.at(intermediateRow); } - - uint64_t originalState; - auto const rowGroups = maybeMatrix.getRowGroupIndices(); - for (originalState = 0; originalState < maybeMatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState + 1]; - if (firstRowStateIndex > originalChoice) { - originalChoice = originalChoice - rowGroups[originalState]; - break; + tmpReducedToOriginalRowIndexMap.push_back(reducedToOriginalRowIndexMap[intermediateRow]); + } + reducedToOriginalRowIndexMap = std::move(tmpReducedToOriginalRowIndexMap); + // originalToReducedStateIndexMap needs to be updated so it maps into the ec-eliminated system + for (uint64_t originalStateIndex = 0; originalStateIndex < transitionMatrix.getRowGroupCount(); ++originalStateIndex) { + auto& reducedIndex = originalToReducedStateIndexMap[originalStateIndex]; + if (maybeStates.get(originalStateIndex)) { + if (ecElimResult1.has_value()) { + reducedIndex = ecElimResult1->oldToNewStateMapping.at(reducedIndex); + } + if (ecElimResult2.has_value()) { + reducedIndex = ecElimResult2->oldToNewStateMapping.at(reducedIndex); } + } else { + reducedIndex = std::numeric_limits::max(); // The original state does not exist in the reduced model. } + } + } - uint64_t index = maybeStates.getNextSetIndex(0); - for (uint64_t s = 0; s < originalState; ++s) { - index = maybeStates.getNextSetIndex(index + 1); - } + storm::storage::BitVector initialComponentExitRows(transitionMatrix.getRowCount(), false); + storm::storage::BitVector initialComponentExitStates(transitionMatrix.getRowGroupCount(), false); + for (auto const reducedRowIndex : matrix.getRowGroupIndices(initStateInReduced)) { + uint64_t const originalRowIndex = reducedToOriginalRowIndexMap[reducedRowIndex]; + uint64_t const originalState = originalRowToStateIndexMap[originalRowIndex]; - originalState = index; - scheduler->setChoice(originalChoice, originalState); - maybeStatesWithChoice.set(originalState, true); - if (state == initStateInMatrix) { - chosenInitialComponentExitState = originalState; - chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState] + originalChoice; - } - ++state; - } + initialComponentExitRows.set(originalRowIndex, true); + initialComponentExitStates.set(originalState, true); + } - std::vector stateToFinalEc(transitionMatrix.getRowGroupCount(), std::numeric_limits::max()); - state = 0; - for (auto s : maybeStates) { - auto mappedState = state; - mappedState = ecElimResult1.has_value() ? ecElimResult1->oldToNewStateMapping[mappedState] : mappedState; - mappedState = ecElimResult2.has_value() ? ecElimResult2->oldToNewStateMapping[mappedState] : mappedState; - stateToFinalEc[s] = mappedState; - state++; + // If requested, construct the scheduler for the original model + storm::storage::BitVector maybeStatesWithChoice(maybeStates.size(), false); + uint64_t chosenInitialComponentExitState = std::numeric_limits::max(); + uint64_t chosenInitialComponentExit = std::numeric_limits::max(); + auto scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + + uint64_t reducedState = 0; + for (auto const& choice : reducedSchedulerChoices.value()) { + uint64_t const reducedRowIndex = matrix.getRowGroupIndices()[reducedState] + choice; + uint64_t const originalRowIndex = reducedToOriginalRowIndexMap[reducedRowIndex]; + uint64_t const originalState = originalRowToStateIndexMap[originalRowIndex]; + uint64_t const originalChoice = originalRowIndex - transitionMatrix.getRowGroupIndices()[originalState]; + scheduler->setChoice(originalChoice, originalState); + maybeStatesWithChoice.set(originalState, true); + if (reducedState == initStateInReduced) { + chosenInitialComponentExitState = originalState; + chosenInitialComponentExit = originalRowIndex; } + ++reducedState; + } - auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, - stateToFinalEc, normalForm, initStateInMatrix, initialComponentExitStates, initialComponentExitRows, - chosenInitialComponentExitState, chosenInitialComponentExit); + auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice; + finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, maybeStates, maybeStatesWithoutChoice, maybeStatesWithChoice, + originalToReducedStateIndexMap, normalForm, initStateInReduced, initialComponentExitStates, initialComponentExitRows, + chosenInitialComponentExitState, chosenInitialComponentExit); - finalResult.scheduler = std::move(scheduler); - } + finalResult.scheduler = std::move(scheduler); return finalResult; } @@ -630,7 +618,7 @@ template class WeightedReachabilityHelper { public: WeightedReachabilityHelper(uint64_t const initialState, storm::storage::SparseMatrix const& transitionMatrix, - NormalFormData const& normalForm) { + NormalFormData const& normalForm, bool computeScheduler) { // Determine rowgroups (states) and rows (choices) of the submatrix auto subMatrixRowGroups = normalForm.maybeStates; // Identify and eliminate the initial component to enforce that it is eventually exited @@ -642,7 +630,7 @@ class WeightedReachabilityHelper { // action. By eliminating the initial component, we ensure that only policies that actually exit C are considered. The remaining policies have // probability zero of satisfying the condition. initialComponentExitRows = storm::storage::BitVector(transitionMatrix.getRowCount(), false); - initialComponentExitStates = storm::storage::BitVector(transitionMatrix.getRowGroupCount(), false); // TODO: use sparse matrix rowfilter + initialComponentExitStates = storm::storage::BitVector(transitionMatrix.getRowGroupCount(), false); subMatrixRowGroups.set(initialState, false); // temporarily unset initial state std::vector dfsStack = {initialState}; while (!dfsStack.empty()) { @@ -669,12 +657,16 @@ class WeightedReachabilityHelper { subMatrixRowGroups.set(initialState, true); // set initial state again, as single representative state for the initial component auto const numSubmatrixRowGroups = subMatrixRowGroups.getNumberOfSetBits(); + if (computeScheduler) { + reducedToOriginalRowIndexMap.reserve(numSubmatrixRows); + } + // state index mapping and initial state - auto stateToMatrixIndexMap = subMatrixRowGroups.getNumberOfSetBitsBeforeIndices(); - initialStateInSubmatrix = stateToMatrixIndexMap[initialState]; + originalToReducedStateIndexMap = subMatrixRowGroups.getNumberOfSetBitsBeforeIndices(); + initialStateInSubmatrix = originalToReducedStateIndexMap[initialState]; auto const eliminatedInitialComponentStates = normalForm.maybeStates & ~subMatrixRowGroups; for (auto state : eliminatedInitialComponentStates) { - stateToMatrixIndexMap[state] = initialStateInSubmatrix; // map all eliminated states to the initial state + originalToReducedStateIndexMap[state] = initialStateInSubmatrix; // map all eliminated states to the initial state } // build matrix, rows that sum up to 1, target values, condition values @@ -707,7 +699,7 @@ class WeightedReachabilityHelper { conditionProbability += scaledTargetValue; // for terminal, non-condition states, the condition value equals the target value } } else if (!eliminatedInitialComponentStates.get(entry.getColumn())) { - auto const columnIndex = stateToMatrixIndexMap[entry.getColumn()]; + auto const columnIndex = originalToReducedStateIndexMap[entry.getColumn()]; if (!initialStateEntryInserted && columnIndex >= initialStateInSubmatrix) { if (columnIndex == initialStateInSubmatrix) { matrixBuilder.addNextValue(currentRow, initialStateInSubmatrix, eliminatedInitialComponentProbability + entry.getValue()); @@ -732,46 +724,58 @@ class WeightedReachabilityHelper { if (state == initialState) { for (auto origRowIndex : initialComponentExitRows) { processRow(origRowIndex); - subMatrixRowToOriginalRow.push_back(origRowIndex); + reducedToOriginalRowIndexMap.push_back(origRowIndex); } } else { for (auto origRowIndex : transitionMatrix.getRowGroupIndices(state)) { processRow(origRowIndex); - subMatrixRowToOriginalRow.push_back(origRowIndex); + reducedToOriginalRowIndexMap.push_back(origRowIndex); } } } - fullSubmatrix = matrixBuilder.build(); // TODO: why copy - submatrix = storm::storage::SparseMatrix(fullSubmatrix); + submatrix = matrixBuilder.build(); // eliminate ECs if present. We already checked that the initial state can not yield observation failure, so it cannot be part of an EC. // For all remaining ECs, staying in an EC forever is reflected by collecting a value of zero for both, target and condition storm::storage::BitVector allExceptInit(numSubmatrixRowGroups, true); allExceptInit.set(initialStateInSubmatrix, false); - ecResult = eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, initialStateInSubmatrix, rowsWithSum1, targetRowValues, - conditionRowValues); + ecResult = eliminateEndComponents(allExceptInit, true, std::nullopt, submatrix, rowsWithSum1, targetRowValues, conditionRowValues); + if (ecResult) { + initialStateInSubmatrix = ecResult->oldToNewStateMapping[initialStateInSubmatrix]; + } isAcyclic = !storm::utility::graph::hasCycle(submatrix); STORM_LOG_INFO("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " << submatrix.getEntryCount() << " transitions. Matrix is " << (isAcyclic ? "acyclic." : "cyclic.")); - // if (ecElimResult.has_value()) { - // ecResult = std::make_unique::EndComponentEliminatorReturnType>(std::move(*ecElimResult)); - // } - - stateToFinalEc.resize(transitionMatrix.getRowGroupCount(), -1); - auto maybeStatesNotInSubmatrix = normalForm.maybeStates & ~subMatrixRowGroups; - - for (auto state : maybeStatesNotInSubmatrix) { - stateToFinalEc[state] = 0; - } - - uint64_t state = 0; - for (auto s : subMatrixRowGroups) { - uint64_t mappedState = state; - mappedState = ecResult.has_value() ? ecResult->oldToNewStateMapping[mappedState] : mappedState; - stateToFinalEc[s] = mappedState; - state++; + if (computeScheduler) { + // For easier conversion of schedulers to the original model, we create and update some index mappings + STORM_LOG_ASSERT(reducedToOriginalRowIndexMap.size() == numSubmatrixRows, "Unexpected size of reducedToOriginalRowIndexMap."); + if (ecResult.has_value()) { + // reducedToOriginalRowIndexMap needs to be updated so it maps from rows of the ec-eliminated system + std::vector tmpReducedToOriginalRowIndexMap; + tmpReducedToOriginalRowIndexMap.reserve(submatrix.getRowCount()); + for (uint64_t reducedRow = 0; reducedRow < submatrix.getRowCount(); ++reducedRow) { + uint64_t intermediateRow = ecResult->newToOldRowMapping.at(reducedRow); + tmpReducedToOriginalRowIndexMap.push_back(reducedToOriginalRowIndexMap[intermediateRow]); + } + reducedToOriginalRowIndexMap = std::move(tmpReducedToOriginalRowIndexMap); + // originalToReducedStateIndexMap needs to be updated so it maps into the ec-eliminated system + for (uint64_t originalStateIndex = 0; originalStateIndex < transitionMatrix.getRowGroupCount(); ++originalStateIndex) { + auto& reducedIndex = originalToReducedStateIndexMap[originalStateIndex]; + if (subMatrixRowGroups.get(originalStateIndex)) { + reducedIndex = ecResult->oldToNewStateMapping.at(reducedIndex); + } else { + reducedIndex = std::numeric_limits::max(); // The original state does not exist in the reduced model. + } + } + } + } else { + // Clear data that is only needed if we compute schedulers + originalToReducedStateIndexMap.clear(); + reducedToOriginalRowIndexMap.clear(); + ecResult.emplace(); + initialComponentExitRows.clear(); + initialComponentExitStates.clear(); } } @@ -878,13 +882,43 @@ class WeightedReachabilityHelper { return improved; } - storm::storage::SparseMatrix submatrix; - storm::storage::SparseMatrix fullSubmatrix; - std::vector stateToFinalEc; - boost::optional::EndComponentEliminatorReturnType> ecResult; - std::vector subMatrixRowToOriginalRow; - storm::storage::BitVector initialComponentExitRows; - storm::storage::BitVector initialComponentExitStates; + std::unique_ptr> constructSchedulerForInputModel( + std::vector const& schedulerForReducedModel, storm::storage::SparseMatrix const& originalTransitionMatrix, + storm::storage::SparseMatrix const& originalBackwardTransitions, NormalFormData const& normalForm) const { + std::vector originalRowToStateIndexMap; // maps original row indices to original state indices. transitionMatrix.getRowGroupIndices() are the + // inverse of that mapping + originalRowToStateIndexMap.reserve(originalTransitionMatrix.getRowCount()); + for (uint64_t originalStateIndex = 0; originalStateIndex < originalTransitionMatrix.getRowGroupCount(); ++originalStateIndex) { + originalRowToStateIndexMap.insert(originalRowToStateIndexMap.end(), originalTransitionMatrix.getRowGroupSize(originalStateIndex), + originalStateIndex); + } + + storm::storage::BitVector maybeStatesWithChoice(normalForm.maybeStates.size(), false); + uint64_t chosenInitialComponentExitState = std::numeric_limits::max(); + uint64_t chosenInitialComponentExit = std::numeric_limits::max(); + auto scheduler = std::make_unique>(originalTransitionMatrix.getRowGroupCount()); + + uint64_t reducedState = 0; + for (auto const& choice : schedulerForReducedModel) { + uint64_t const reducedRowIndex = submatrix.getRowGroupIndices()[reducedState] + choice; + uint64_t const originalRowIndex = reducedToOriginalRowIndexMap[reducedRowIndex]; + uint64_t const originalState = originalRowToStateIndexMap[originalRowIndex]; + uint64_t const originalChoice = originalRowIndex - originalTransitionMatrix.getRowGroupIndices()[originalState]; + scheduler->setChoice(originalChoice, originalState); + maybeStatesWithChoice.set(originalState, true); + if (reducedState == initialStateInSubmatrix) { + chosenInitialComponentExitState = originalState; + chosenInitialComponentExit = originalRowIndex; + } + ++reducedState; + } + + auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; + finalizeSchedulerForMaybeStates(*scheduler, originalTransitionMatrix, originalBackwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, + maybeStatesWithChoice, originalToReducedStateIndexMap, normalForm, initialStateInSubmatrix, initialComponentExitStates, + initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); + return scheduler; + } private: void createScaledVector(std::vector& out, ValueType const& w1, std::vector const& v1, ValueType const& w2, @@ -917,12 +951,19 @@ class WeightedReachabilityHelper { std::unique_ptr> cachedSolver; std::vector cachedX; std::vector cachedB; + + // Data used to translate schedulers: + std::vector originalToReducedStateIndexMap; + std::vector reducedToOriginalRowIndexMap; + std::optional::EndComponentEliminatorReturnType> ecResult; + storm::storage::BitVector initialComponentExitRows; + storm::storage::BitVector initialComponentExitStates; }; template -typename internal::ResultReturnType computeViaBisection(Environment const& env, bool const useAdvancedBounds, bool const usePolicyTracking, uint64_t const initialState, - storm::solver::SolveGoal goal, bool computeScheduler, - storm::storage::SparseMatrix const& transitionMatrix, +typename internal::ResultReturnType computeViaBisection(Environment const& env, bool const useAdvancedBounds, bool const usePolicyTracking, + uint64_t const initialState, storm::solver::SolveGoal const& goal, + bool computeScheduler, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper @@ -937,7 +978,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c }(); bool const relative = env.solver().minMax().getRelativeTerminationCriterion(); - WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm); + WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm, computeScheduler); SolutionType pMin{storm::utility::zero()}; SolutionType pMax{storm::utility::one()}; @@ -1086,83 +1127,41 @@ typename internal::ResultReturnType computeViaBisection(Environment c // Create result without scheduler auto finalResult = ResultReturnType((*lowerBound + *upperBound) / 2); + if (!computeScheduler) { + return finalResult; // nothing else to do + } // If requested, construct the scheduler for the original model - if (computeScheduler) { - std::vector resultSchedulerChoices; - if (usePolicyTracking && *lowerBound == *upperBound) { - // We already have computed a scheduler - resultSchedulerChoices = std::move(*lowerScheduler); - } else { - // Compute a scheduler on the middle result - wrh.computeWeightedDiff(env, goal.direction(), storm::utility::one(), -finalResult.initialStateValue, resultSchedulerChoices); - - } - storm::storage::BitVector maybeStatesWithChoice(normalForm.maybeStates.size(), false); - std::unique_ptr> scheduler; - uint64_t chosenInitialComponentExitState; - uint64_t chosenInitialComponentExit; - scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); - - uint64_t state = 0; - for (auto& choice : *res.scheduler) { - uint64_t originalChoice; - uint64_t originalState; - - uint64_t firstRowIndex = wrh.submatrix.getRowGroupIndices()[state]; - originalChoice = firstRowIndex + choice; - if (wrh.ecResult.has_value()) { - originalChoice = wrh.ecResult->newToOldRowMapping[originalChoice]; - } - - originalChoice = wrh.subMatrixRowToOriginalRow[originalChoice]; - - auto const& rowGroups = transitionMatrix.getRowGroupIndices(); - for (originalState = 0; originalState < transitionMatrix.getRowGroupCount(); ++originalState) { - auto const firstRowStateIndex = rowGroups[originalState + 1]; - if (firstRowStateIndex > originalChoice) { - originalChoice = originalChoice - rowGroups[originalState]; - break; - } - } - - scheduler->setChoice(originalChoice, originalState); - maybeStatesWithChoice.set(originalState, true); - - if (state == wrh.getInternalInitialState()) { - chosenInitialComponentExitState = originalState; - chosenInitialComponentExit = transitionMatrix.getRowGroupIndices()[originalState] + originalChoice; - } - - ++state; - } - - auto const maybeStatesWithoutChoice = normalForm.maybeStates & ~maybeStatesWithChoice; - finalizeSchedulerForMaybeStates(*scheduler, transitionMatrix, backwardTransitions, normalForm.maybeStates, maybeStatesWithoutChoice, - maybeStatesWithChoice, wrh.stateToFinalEc, normalForm, wrh.getInternalInitialState(), wrh.initialComponentExitStates, - wrh.initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit); - - finalResult.scheduler = std::move(scheduler); + std::vector reducedSchedulerChoices; + if (usePolicyTracking && *lowerBound == *upperBound) { + // We already have computed a scheduler + reducedSchedulerChoices = std::move(*lowerScheduler); + } else { + // Compute a scheduler on the middle result by performing one more iteration + wrh.computeWeightedDiff(env, goal.direction(), storm::utility::one(), -finalResult.initialStateValue, reducedSchedulerChoices); } - + finalResult.scheduler = wrh.constructSchedulerForInputModel(reducedSchedulerChoices, transitionMatrix, backwardTransitions, normalForm); return finalResult; } template -SolutionType computeViaBisection(Environment const& env, ConditionalAlgorithmSetting const alg, uint64_t const initialState, - storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, - NormalFormData const& normalForm) { +typename internal::ResultReturnType computeViaBisection(Environment const& env, ConditionalAlgorithmSetting const alg, uint64_t const initialState, + storm::solver::SolveGoal const& goal, bool computeScheduler, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + NormalFormData const& normalForm) { using enum ConditionalAlgorithmSetting; STORM_LOG_ASSERT(alg == Bisection || alg == BisectionAdvanced || alg == BisectionPolicyTracking || alg == BisectionAdvancedPolicyTracking, "Unhandled Bisection algorithm " << alg << "."); bool const useAdvancedBounds = (alg == BisectionAdvanced || alg == BisectionAdvancedPolicyTracking); bool const usePolicyTracking = (alg == BisectionPolicyTracking || alg == BisectionAdvancedPolicyTracking); - return computeViaBisection(env, useAdvancedBounds, usePolicyTracking, initialState, dir, transitionMatrix, normalForm); + return computeViaBisection(env, useAdvancedBounds, usePolicyTracking, initialState, goal, computeScheduler, transitionMatrix, backwardTransitions, + normalForm); } template SolutionType computeViaPolicyIteration(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { - WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm); + WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm, false); // scheduler computation not yet implemented. std::vector scheduler; std::vector targetResults, conditionResults; @@ -1272,15 +1271,14 @@ std::unique_ptr computeConditionalProbabilities(Environment const& initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; - case ConditionalAlgorithmSetting::Restart: - initialStateValue = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); - break; + } case ConditionalAlgorithmSetting::Bisection: case ConditionalAlgorithmSetting::BisectionAdvanced: case ConditionalAlgorithmSetting::BisectionPolicyTracking: - case ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking: - auto result = internal::computeViaBisection(analysisEnv, alg, initialState, goal.direction(), transitionMatrix, normalFormData); - initialStateValue = result.initialStateValue; + case ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking: { + auto result = internal::computeViaBisection(analysisEnv, alg, initialState, goal, checkTask.isProduceSchedulersSet(), transitionMatrix, + backwardTransitions, normalFormData); + initialStateValue = result.initialStateValue; scheduler = std::move(result.scheduler); break; } diff --git a/src/storm/storage/MaximalEndComponentDecomposition.cpp b/src/storm/storage/MaximalEndComponentDecomposition.cpp index 1df4402f1d..1470fbcd70 100644 --- a/src/storm/storage/MaximalEndComponentDecomposition.cpp +++ b/src/storm/storage/MaximalEndComponentDecomposition.cpp @@ -150,6 +150,8 @@ void MaximalEndComponentDecomposition::performMaximalEndComponentDeco storm::storage::SparseMatrix const& backwardTransitions, storm::OptionalRef states, storm::OptionalRef choices) { + STORM_LOG_ASSERT(!states.has_value() || transitionMatrix.getRowGroupCount() == states->size(), "Unexpected size of states bitvector."); + STORM_LOG_ASSERT(!choices.has_value() || transitionMatrix.getRowCount() == choices->size(), "Unexpected size of choices bitvector."); // Get some data for convenient access. auto const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices(); From 5c74e7df4999b6b9f16919ea090abde3d17507d9 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Thu, 15 Jan 2026 17:29:15 +0100 Subject: [PATCH 085/102] Optimizations for thresholded properties --- .../modelchecker/ModelCheckerEnvironment.cpp | 9 ++ .../modelchecker/ModelCheckerEnvironment.h | 4 + .../helper/conditional/ConditionalHelper.cpp | 82 +++++++++++++++---- src/storm/solver/SolveGoal.cpp | 5 ++ src/storm/solver/SolveGoal.h | 2 + .../ConditionalMdpPrctlModelCheckerTest.cpp | 17 +++- 6 files changed, 102 insertions(+), 17 deletions(-) diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp index 5ff79fd9a3..7950f78813 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp @@ -21,6 +21,7 @@ ModelCheckerEnvironment::ModelCheckerEnvironment() { steadyStateDistributionAlgorithm = ioSettings.getSteadyStateDistributionAlgorithm(); conditionalAlgorithmSetting = mcSettings.getConditionalAlgorithmSetting(); + allowOptimizationForBoundedProperties = true; } ModelCheckerEnvironment::~ModelCheckerEnvironment() { @@ -43,6 +44,14 @@ void ModelCheckerEnvironment::setConditionalAlgorithmSetting(ConditionalAlgorith conditionalAlgorithmSetting = value; } +bool ModelCheckerEnvironment::isAllowOptimizationForBoundedPropertiesSet() const { + return allowOptimizationForBoundedProperties; +} + +void ModelCheckerEnvironment::setAllowOptimizationForBoundedProperties(bool value) { + allowOptimizationForBoundedProperties = value; +} + MultiObjectiveModelCheckerEnvironment& ModelCheckerEnvironment::multi() { return multiObjectiveModelCheckerEnvironment.get(); } diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h index fce3e9e337..da4a398e91 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h @@ -28,6 +28,9 @@ class ModelCheckerEnvironment { ConditionalAlgorithmSetting getConditionalAlgorithmSetting() const; void setConditionalAlgorithmSetting(ConditionalAlgorithmSetting value); + bool isAllowOptimizationForBoundedPropertiesSet() const; + void setAllowOptimizationForBoundedProperties(bool value); + bool isLtl2daToolSet() const; std::string const& getLtl2daTool() const; void setLtl2daTool(std::string const& value); @@ -38,5 +41,6 @@ class ModelCheckerEnvironment { boost::optional ltl2daTool; SteadyStateDistributionAlgorithm steadyStateDistributionAlgorithm; ConditionalAlgorithmSetting conditionalAlgorithmSetting; + bool allowOptimizationForBoundedProperties; }; } // namespace storm diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 7e8adfab7a..9021847151 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -88,14 +88,26 @@ std::optional::En template SolutionType solveMinMaxEquationSystem(storm::Environment const& env, storm::storage::SparseMatrix const& matrix, std::vector const& rowValues, storm::storage::BitVector const& rowsWithSum1, - storm::solver::OptimizationDirection const dir, uint64_t const initialState, + storm::solver::SolveGoal const& goal, uint64_t const initialState, std::optional>& schedulerOutput) { // Initialize the solution vector. std::vector x(matrix.getRowGroupCount(), storm::utility::zero()); // Set up the solver. - auto solver = storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(env, matrix); - solver->setOptimizationDirection(dir); + storm::solver::GeneralMinMaxLinearEquationSolverFactory factory; + storm::storage::BitVector relevantValues(matrix.getRowGroupCount(), false); + relevantValues.set(initialState, true); + auto getGoal = [&env, &goal, &relevantValues]() -> storm::solver::SolveGoal { + if (goal.isBounded() && env.modelchecker().isAllowOptimizationForBoundedPropertiesSet()) { + return {goal.direction(), goal.boundComparisonType(), goal.thresholdValue(), relevantValues}; + } else { + return {goal.direction(), relevantValues}; + } + }; + auto solver = storm::solver::configureMinMaxLinearEquationSolver(env, getGoal(), factory, matrix); + + storm::solver::GeneralMinMaxLinearEquationSolverFactory().create(env, matrix); + solver->setOptimizationDirection(goal.direction()); solver->setRequirementsChecked(); solver->setHasUniqueSolution(true); solver->setHasNoEndComponents(true); @@ -420,7 +432,7 @@ struct ResultReturnType { */ template typename internal::ResultReturnType computeViaRestartMethod(Environment const& env, uint64_t const initialState, - storm::solver::OptimizationDirection const dir, bool computeScheduler, + storm::solver::SolveGoal const& goal, bool computeScheduler, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { @@ -512,7 +524,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme if (computeScheduler) { reducedSchedulerChoices.emplace(); } - auto resultValue = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, dir, initStateInReduced, reducedSchedulerChoices); + auto resultValue = solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, goal, initStateInReduced, reducedSchedulerChoices); // Create result (scheduler potentially added below) auto finalResult = ResultReturnType(resultValue); @@ -1159,8 +1171,41 @@ typename internal::ResultReturnType computeViaBisection(Environment c } template -SolutionType computeViaPolicyIteration(Environment const& env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, - storm::storage::SparseMatrix const& transitionMatrix, NormalFormData const& normalForm) { +typename internal::ResultReturnType decideThreshold(Environment const& env, uint64_t const initialState, + storm::OptimizationDirection const& direction, SolutionType const& threshold, + bool computeScheduler, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + NormalFormData const& normalForm) { + // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper + + WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm, computeScheduler); + + std::optional> scheduler; + storm::OptionalRef> schedulerRef; + if (computeScheduler) { + scheduler.emplace(); + schedulerRef.reset(*scheduler); + } + + SolutionType val = wrh.computeWeightedDiff(env, direction, storm::utility::one(), -threshold, schedulerRef); + // if val is positive, the conditional probability is (strictly) greater than threshold + // if val is negative, the conditional probability is (strictly) smaller than threshold + // if val is zero, the conditional probability equals the threshold + // so, for the true probability p and comparison ~ we have: p ~ threshold <=> val + threshold ~ threshold + auto finalResult = ResultReturnType(val + threshold); + + if (computeScheduler) { + // If requested, construct the scheduler for the original model + finalResult.scheduler = wrh.constructSchedulerForInputModel(scheduler.value(), transitionMatrix, backwardTransitions, normalForm); + } + return finalResult; +} + +template +internal::ResultReturnType computeViaPolicyIteration(Environment const& env, uint64_t const initialState, + storm::solver::OptimizationDirection const dir, + storm::storage::SparseMatrix const& transitionMatrix, + NormalFormData const& normalForm) { WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm, false); // scheduler computation not yet implemented. std::vector scheduler; @@ -1264,32 +1309,37 @@ std::unique_ptr computeConditionalProbabilities(Environment const& } STORM_LOG_INFO("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg << "."); // sw.restart(); + internal::ResultReturnType result{storm::utility::zero()}; switch (alg) { case ConditionalAlgorithmSetting::Restart: { - auto result = internal::computeViaRestartMethod(analysisEnv, initialState, goal.direction(), checkTask.isProduceSchedulersSet(), - transitionMatrix, backwardTransitions, normalFormData); - initialStateValue = result.initialStateValue; - scheduler = std::move(result.scheduler); + result = internal::computeViaRestartMethod(analysisEnv, initialState, goal, checkTask.isProduceSchedulersSet(), transitionMatrix, + backwardTransitions, normalFormData); break; } case ConditionalAlgorithmSetting::Bisection: case ConditionalAlgorithmSetting::BisectionAdvanced: case ConditionalAlgorithmSetting::BisectionPolicyTracking: case ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking: { - auto result = internal::computeViaBisection(analysisEnv, alg, initialState, goal, checkTask.isProduceSchedulersSet(), transitionMatrix, - backwardTransitions, normalFormData); - initialStateValue = result.initialStateValue; - scheduler = std::move(result.scheduler); + if (goal.isBounded() && env.modelchecker().isAllowOptimizationForBoundedPropertiesSet()) { + result = internal::decideThreshold(analysisEnv, initialState, goal.direction(), goal.thresholdValue(), checkTask.isProduceSchedulersSet(), + transitionMatrix, backwardTransitions, normalFormData); + } else { + result = internal::computeViaBisection(analysisEnv, alg, initialState, goal, checkTask.isProduceSchedulersSet(), transitionMatrix, + backwardTransitions, normalFormData); + } break; } case ConditionalAlgorithmSetting::PolicyIteration: { - initialStateValue = internal::computeViaPolicyIteration(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); + result = internal::computeViaPolicyIteration(analysisEnv, initialState, goal.direction(), transitionMatrix, normalFormData); break; } default: { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Unknown conditional probability algorithm: " << alg); } } + initialStateValue = result.initialStateValue; + scheduler = std::move(result.scheduler); + // sw.stop(); // STORM_PRINT_AND_LOG("Time for analyzing the normal form: " << sw << ".\n"); } diff --git a/src/storm/solver/SolveGoal.cpp b/src/storm/solver/SolveGoal.cpp index 1f23b34f3f..c363df4664 100644 --- a/src/storm/solver/SolveGoal.cpp +++ b/src/storm/solver/SolveGoal.cpp @@ -109,6 +109,11 @@ bool SolveGoal::isRobust() const { return robustAgainstUncertainty; } +template +storm::logic::ComparisonType SolveGoal::boundComparisonType() const { + return comparisonType.get(); +} + template SolutionType const& SolveGoal::thresholdValue() const { return threshold.get(); diff --git a/src/storm/solver/SolveGoal.h b/src/storm/solver/SolveGoal.h index f5f672f8e1..78237a5355 100644 --- a/src/storm/solver/SolveGoal.h +++ b/src/storm/solver/SolveGoal.h @@ -84,6 +84,8 @@ class SolveGoal { bool boundIsStrict() const; + storm::logic::ComparisonType boundComparisonType() const; + SolutionType const& thresholdValue() const; bool hasRelevantValues() const; diff --git a/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp index 597a78bfee..572be8909f 100644 --- a/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/ConditionalMdpPrctlModelCheckerTest.cpp @@ -8,6 +8,7 @@ #include "storm/environment/modelchecker/ModelCheckerEnvironment.h" #include "storm/environment/solver/MinMaxSolverEnvironment.h" #include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h" +#include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" namespace { @@ -118,6 +119,7 @@ class SparseRationalNumberBisectionAdvancedEnvironment { static storm::Environment createEnvironment() { storm::Environment env; env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionAdvanced); + env.solver().minMax().setPrecision(storm::utility::convertNumber(0)); // TODO: this should not be necessary return env; } }; @@ -142,6 +144,7 @@ class SparseRationalNumberBisectionAdvancedPtEnvironment { static storm::Environment createEnvironment() { storm::Environment env; env.modelchecker().setConditionalAlgorithmSetting(storm::ConditionalAlgorithmSetting::BisectionAdvancedPolicyTracking); + env.solver().minMax().setPrecision(storm::utility::convertNumber(0)); // TODO: this should not be necessary return env; } }; @@ -263,7 +266,11 @@ TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, consensus) { "Pmax=? [F \"all_coins_equal_0\" & \"finished\" || F \"agree\" & \"finished\"];" "Pmin=? [F \"all_coins_equal_0\" & \"finished\" || F \"agree\" & \"finished\"];" "Pmax=? [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];" - "Pmin=? [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];"; + "Pmin=? [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];" + "P<=560/953 [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];" + "P<562/953 [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];" + "P>393/953 [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];" + "P>=391/953 [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];"; auto program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm"); auto modelFormulas = this->buildModelFormulas(program, formulasString); @@ -283,6 +290,14 @@ TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, consensus) { EXPECT_NEAR(this->parseNumber("561/953"), result[*mdp->getInitialStates().begin()], this->precision()); result = checker.check(this->env(), tasks[3])->template asExplicitQuantitativeCheckResult(); EXPECT_NEAR(this->parseNumber("392/953"), result[*mdp->getInitialStates().begin()], this->precision()); + auto qualResult = checker.check(this->env(), tasks[4])->template asExplicitQualitativeCheckResult(); + EXPECT_FALSE(qualResult[*mdp->getInitialStates().begin()]); + qualResult = checker.check(this->env(), tasks[5])->template asExplicitQualitativeCheckResult(); + EXPECT_TRUE(qualResult[*mdp->getInitialStates().begin()]); + qualResult = checker.check(this->env(), tasks[6])->template asExplicitQualitativeCheckResult(); + EXPECT_FALSE(qualResult[*mdp->getInitialStates().begin()]); + qualResult = checker.check(this->env(), tasks[7])->template asExplicitQualitativeCheckResult(); + EXPECT_TRUE(qualResult[*mdp->getInitialStates().begin()]); } TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, simple) { From 9a6a87a47418cf405312beed06c87fad74e04824 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Thu, 22 Jan 2026 12:24:25 +0100 Subject: [PATCH 086/102] Fix issue with policy tracking and policy export --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 9021847151..e1e5eccd8c 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -1016,6 +1016,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c [[maybe_unused]] SolutionType rationalCandiate = middle; // relevant for exact computations [[maybe_unused]] uint64_t rationalCandidateCount = 0; std::set checkedMiddleValues; // Middle values that have been checked already + bool terminatedThroughPolicyTracking = false; for (uint64_t iterationCount = 1; true; ++iterationCount) { // evaluate the current middle SolutionType const middleValue = wrh.computeWeightedDiff(env, goal.direction(), storm::utility::one(), -middle, middleSchedulerRef); @@ -1081,6 +1082,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c auto result = wrh.evaluateScheduler(env, *lowerScheduler); lowerBound &= result; upperBound &= result; + terminatedThroughPolicyTracking = true; break; } // Check if bounds are fully below or above threshold @@ -1144,7 +1146,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c } // If requested, construct the scheduler for the original model std::vector reducedSchedulerChoices; - if (usePolicyTracking && *lowerBound == *upperBound) { + if (terminatedThroughPolicyTracking) { // We already have computed a scheduler reducedSchedulerChoices = std::move(*lowerScheduler); } else { From 27100ac2363b3e4c9d26fa29ba0bb4f237a9c4a8 Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Fri, 23 Jan 2026 10:06:14 +0100 Subject: [PATCH 087/102] add setting for experiments --- .../modelchecker/ModelCheckerEnvironment.cpp | 10 +++++++ .../modelchecker/ModelCheckerEnvironment.h | 6 ++++ .../helper/conditional/ConditionalHelper.cpp | 29 +++++++++---------- .../settings/modules/ModelCheckerSettings.cpp | 16 +++++++++- .../settings/modules/ModelCheckerSettings.h | 7 +++++ ...IntervalEndComponentPreserverCheckTest.cpp | 2 +- 6 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp index 7950f78813..5c8efb8333 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp @@ -21,6 +21,7 @@ ModelCheckerEnvironment::ModelCheckerEnvironment() { steadyStateDistributionAlgorithm = ioSettings.getSteadyStateDistributionAlgorithm(); conditionalAlgorithmSetting = mcSettings.getConditionalAlgorithmSetting(); + conditionalToleranceSetting = mcSettings.getConditionalTolerance(); allowOptimizationForBoundedProperties = true; } @@ -44,6 +45,15 @@ void ModelCheckerEnvironment::setConditionalAlgorithmSetting(ConditionalAlgorith conditionalAlgorithmSetting = value; } +void ModelCheckerEnvironment::setConditionalTolerance(storm::RationalNumber const& value) { + conditionalToleranceSetting = value; +} + + +storm::RationalNumber ModelCheckerEnvironment::getConditionalTolerance() const { + return conditionalToleranceSetting; +} + bool ModelCheckerEnvironment::isAllowOptimizationForBoundedPropertiesSet() const { return allowOptimizationForBoundedProperties; } diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h index da4a398e91..8cd86c06c9 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h @@ -8,6 +8,7 @@ #include "storm/environment/SubEnvironment.h" #include "storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h" #include "storm/modelchecker/helper/infinitehorizon/SteadyStateDistributionAlgorithm.h" +#include "storm/adapters/RationalNumberAdapter.h" namespace storm { @@ -28,6 +29,10 @@ class ModelCheckerEnvironment { ConditionalAlgorithmSetting getConditionalAlgorithmSetting() const; void setConditionalAlgorithmSetting(ConditionalAlgorithmSetting value); + // TODO: This should probably be moved. + storm::RationalNumber getConditionalTolerance() const; + void setConditionalTolerance(storm::RationalNumber const& value); + bool isAllowOptimizationForBoundedPropertiesSet() const; void setAllowOptimizationForBoundedProperties(bool value); @@ -42,5 +47,6 @@ class ModelCheckerEnvironment { SteadyStateDistributionAlgorithm steadyStateDistributionAlgorithm; ConditionalAlgorithmSetting conditionalAlgorithmSetting; bool allowOptimizationForBoundedProperties; + storm::RationalNumber conditionalToleranceSetting; }; } // namespace storm diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 9021847151..292ee9fd9a 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -979,15 +979,13 @@ typename internal::ResultReturnType computeViaBisection(Environment c storm::storage::SparseMatrix const& backwardTransitions, NormalFormData const& normalForm) { // We currently handle sound model checking incorrectly: we would need the actual lower/upper bounds of the weightedReachabilityHelper - STORM_LOG_WARN_COND(!env.solver().isForceSoundness(), - "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); SolutionType const precision = [&env]() { - // if (storm::NumberTraits::IsExact || env.solver().isForceExact()) { - // return storm::utility::zero(); - // } else { - return storm::utility::convertNumber(env.solver().minMax().getPrecision()); - // } + // TODO: Discussed that this may be better in the solveGoal or checkTask, but lets be pragmatic today. + return storm::utility::convertNumber(env.modelchecker().getConditionalTolerance()); }(); + STORM_LOG_WARN_COND(!(env.solver().isForceSoundness() && storm::utility::isZero(precision)), + "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound."); + bool const relative = env.solver().minMax().getRelativeTerminationCriterion(); WeightedReachabilityHelper wrh(initialState, transitionMatrix, normalForm, computeScheduler); @@ -1271,14 +1269,15 @@ std::unique_ptr computeConditionalProbabilities(Environment const& // We might require adapting the precision of the solver to counter error propagation (e.g. when computing the normal form). auto normalFormConstructionEnv = env; auto analysisEnv = env; - if (env.solver().isForceSoundness()) { - // We intuitively have to divide the precision into two parts, one for computations when constructing the normal form and one for the actual analysis. - // As the former is usually less numerically challenging, we use a factor of 1/10 for the normal form construction and 9/10 for the analysis. - auto const normalFormPrecisionFactor = storm::utility::convertNumber("1/10"); - normalFormConstructionEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * normalFormPrecisionFactor); - analysisEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * - (storm::utility::one() - normalFormPrecisionFactor)); - } + +// if (env.solver().isForceSoundness()) { +// // We intuitively have to divide the precision into two parts, one for computations when constructing the normal form and one for the actual analysis. +// // As the former is usually less numerically challenging, we use a factor of 1/10 for the normal form construction and 9/10 for the analysis. +// auto const normalFormPrecisionFactor = storm::utility::convertNumber("1/10"); +// normalFormConstructionEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * normalFormPrecisionFactor); +// analysisEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * +// (storm::utility::one() - normalFormPrecisionFactor)); +// } // We first translate the problem into a normal form. // @see doi.org/10.1007/978-3-642-54862-8_43 diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index 4689ee7802..7833aa039e 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -5,6 +5,7 @@ #include "storm/settings/Option.h" #include "storm/settings/OptionBuilder.h" #include "storm/settings/SettingsManager.h" +#include "storm/utility/constants.h" namespace storm::settings::modules { @@ -12,6 +13,8 @@ const std::string ModelCheckerSettings::moduleName = "modelchecker"; const std::string ModelCheckerSettings::filterRewZeroOptionName = "filterrewzero"; const std::string ModelCheckerSettings::ltl2daToolOptionName = "ltl2datool"; const std::string ModelCheckerSettings::conditionalAlgorithmOptionName = "conditional"; +static const std::string conditionalToleranceName = "conditional-tolerance"; + ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, filterRewZeroOptionName, false, @@ -28,12 +31,19 @@ ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { std::vector const conditionalAlgs = {"default", "restart", "bisection", "bisection-advanced", "bisection-pt", "bisection-advanced-pt", "pi"}; this->addOption(storm::settings::OptionBuilder(moduleName, conditionalAlgorithmOptionName, false, "The used algorithm for conditional probabilities.") - .setIsAdvanced() .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the method to use.") .addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(conditionalAlgs)) .setDefaultValueString("default") .build()) .build()); + // Would be better if there was a createRationalArgument . + this->addOption(storm::settings::OptionBuilder(moduleName, conditionalToleranceName, false, "The internally used tolerance for computing conditional probabilities..") + .setShortName("condtol") + .addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to use.") + .setDefaultValueDouble(1e-04) + .addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorExcluding(0.0, 1.0)) + .build()) + .build()); } bool ModelCheckerSettings::isFilterRewZeroSet() const { @@ -52,6 +62,10 @@ bool ModelCheckerSettings::isConditionalAlgorithmSet() const { return this->getOption(conditionalAlgorithmOptionName).getHasOptionBeenSet(); } +storm::RationalNumber ModelCheckerSettings::getConditionalTolerance() const { + return storm::utility::convertNumber(this->getOption(conditionalToleranceName).getArgumentByName("value").getValueAsDouble()); +} + ConditionalAlgorithmSetting ModelCheckerSettings::getConditionalAlgorithmSetting() const { return conditionalAlgorithmSettingFromString(this->getOption(conditionalAlgorithmOptionName).getArgumentByName("name").getValueAsString()); } diff --git a/src/storm/settings/modules/ModelCheckerSettings.h b/src/storm/settings/modules/ModelCheckerSettings.h index ce7e5bd234..70fc7b43a5 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.h +++ b/src/storm/settings/modules/ModelCheckerSettings.h @@ -3,6 +3,7 @@ #include "storm-config.h" #include "storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h" #include "storm/settings/modules/ModuleSettings.h" +#include "storm/adapters/RationalNumberAdapter.h" namespace storm { namespace settings { @@ -44,6 +45,12 @@ class ModelCheckerSettings : public ModuleSettings { */ ConditionalAlgorithmSetting getConditionalAlgorithmSetting() const; + /*! + * TODO probably generalize + * Retrieves + */ + storm::RationalNumber getConditionalTolerance() const; + // The name of the module. static const std::string moduleName; diff --git a/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp b/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp index 4956c8ef73..854254cae9 100644 --- a/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp +++ b/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp @@ -41,7 +41,7 @@ void testModelInterval(std::string programFile, std::string formulaAsString, std storm::modelchecker::SparsePropositionalModelChecker> propositionalChecker(*dtmc); storm::storage::BitVector psiStates = propositionalChecker.check(checkTask.getFormula().asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->asExplicitQualitativeCheckResult() + ->asExplicitQualitativeCheckResult() .getTruthValuesVector(); std::vector target(model->getNumberOfStates(), storm::utility::zero()); From efc6c0315a483e8799dda121bdbf129c7469148b Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Fri, 23 Jan 2026 10:06:40 +0100 Subject: [PATCH 088/102] refined add uncertainty to avoid adding uncertainty to states with many successors --- src/storm/storage/SparseMatrix.cpp | 12 +++++++++--- src/storm/storage/SparseMatrix.h | 7 +++++++ src/storm/transformer/AddUncertainty.cpp | 12 +++++++++--- src/storm/transformer/AddUncertainty.h | 2 +- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/storm/storage/SparseMatrix.cpp b/src/storm/storage/SparseMatrix.cpp index d64bfc0f94..0600f72061 100644 --- a/src/storm/storage/SparseMatrix.cpp +++ b/src/storm/storage/SparseMatrix.cpp @@ -672,17 +672,23 @@ typename SparseMatrix::index_type SparseMatrix::getEntryCo template typename SparseMatrix::index_type SparseMatrix::getRowGroupEntryCount(index_type const group) const { - index_type result = 0; if (!this->hasTrivialRowGrouping()) { + index_type result = 0; for (auto row : this->getRowGroupIndices(group)) { result += (this->rowIndications[row + 1] - this->rowIndications[row]); } + return result; } else { - result += (this->rowIndications[group + 1] - this->rowIndications[group]); + return (this->rowIndications[group + 1] - this->rowIndications[group]); } - return result; } +template +typename SparseMatrix::index_type SparseMatrix::getRowEntryCount(index_type const row) const { + return (this->rowIndications[row + 1] - this->rowIndications[row]); +} + + template typename SparseMatrix::index_type SparseMatrix::getNonzeroEntryCount() const { return nonzeroEntryCount; diff --git a/src/storm/storage/SparseMatrix.h b/src/storm/storage/SparseMatrix.h index 5ccccceb85..f7eea9c4ce 100644 --- a/src/storm/storage/SparseMatrix.h +++ b/src/storm/storage/SparseMatrix.h @@ -531,6 +531,13 @@ class SparseMatrix { */ index_type getRowGroupEntryCount(index_type const group) const; + /*! + * Returns the number of entries in the given row of the matrix. + * @param row Which row + * @return Number of entries + */ + index_type getRowEntryCount(index_type const row) const; + /*! * Returns the cached number of nonzero entries in the matrix. * diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index 9c7af818b2..e62388a048 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -17,15 +17,21 @@ template AddUncertainty::AddUncertainty(std::shared_ptr> const& originalModel) : origModel(originalModel) {} template -std::shared_ptr> AddUncertainty::transform(double additiveUncertainty, double minimalTransitionProbability) { +std::shared_ptr> AddUncertainty::transform(double additiveUncertainty, double minimalTransitionProbability, uint64_t maxSuccessors) { // we first build the matrix and later copy the row grouping. auto newMatrixBuilder = storage::SparseMatrixBuilder(origModel->getTransitionMatrix().getRowCount(), origModel->getTransitionMatrix().getColumnCount(), origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); // Build transition matrix (without row grouping) for (uint64_t rowIndex = 0; rowIndex < origModel->getTransitionMatrix().getRowCount(); ++rowIndex) { - for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { - newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), additiveUncertainty, minimalTransitionProbability)); + if (origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors) { + for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { + newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), additiveUncertainty, minimalTransitionProbability)); + } + } else { + for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { + newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), 0, 0)); + } } } storm::storage::sparse::ModelComponents modelComponents(newMatrixBuilder.build(), origModel->getStateLabeling()); diff --git a/src/storm/transformer/AddUncertainty.h b/src/storm/transformer/AddUncertainty.h index f31088c1ca..e5f0f4fab7 100644 --- a/src/storm/transformer/AddUncertainty.h +++ b/src/storm/transformer/AddUncertainty.h @@ -16,7 +16,7 @@ template class AddUncertainty { public: AddUncertainty(std::shared_ptr> const& originalModel); - std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001); + std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001, uint64_t maxSuccessors = 10000000); private: storm::Interval addUncertainty(ValueType const& vt, double additiveUncertainty, double minimalValue); From bbd62832dd941dc9a944c05f92c194af1781eb03 Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Fri, 23 Jan 2026 12:25:24 +0100 Subject: [PATCH 089/102] Fixed case where all initial component states are good --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index e1e5eccd8c..463aa2ac5e 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -361,15 +361,16 @@ void finalizeSchedulerForMaybeStates(storm::storage::Scheduler& sc storm::storage::BitVector choicesAllowedForInitialComponent = allowedChoices & ~disallowedInitialComponentExits; storm::storage::BitVector goodInitialComponentStates = initialComponentStates; + bool progress = false; for (auto state : initialComponentExitStates) { auto const groupStart = transitionMatrix.getRowGroupIndices()[state]; auto const groupEnd = transitionMatrix.getRowGroupIndices()[state + 1]; bool const allChoicesAreDisallowed = disallowedInitialComponentExits.getNextUnsetIndex(groupStart) >= groupEnd; if (allChoicesAreDisallowed) { goodInitialComponentStates.set(state, false); + progress = true; } } - bool progress = true; while (progress) { progress = false; for (auto state : goodInitialComponentStates) { From e608801e487b5d6cb8140c8b19320777fb488306 Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Fri, 23 Jan 2026 19:59:57 +0100 Subject: [PATCH 090/102] print iterations and fix tolerance --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 8 ++++---- src/storm/settings/modules/ModelCheckerSettings.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 5d22f73ce7..14586976b4 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -1072,12 +1072,12 @@ typename internal::ResultReturnType computeViaBisection(Environment c << "."); } if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { - STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations. Difference is " + STORM_PRINT_AND_LOG("Bisection method converged after " << iterationCount << " iterations. Difference is " << std::setprecision(std::numeric_limits::digits10) << storm::utility::convertNumber(boundDiff) << "."); break; } else if (usePolicyTracking && lowerScheduler && upperScheduler && (*lowerScheduler == *upperScheduler)) { - STORM_LOG_INFO("Bisection method converged after " << iterationCount << " iterations due to identical schedulers for lower and upper bound."); + STORM_PRINT_AND_LOG("Bisection method converged after " << iterationCount << " iterations due to identical schedulers for lower and upper bound."); auto result = wrh.evaluateScheduler(env, *lowerScheduler); lowerBound &= result; upperBound &= result; @@ -1086,7 +1086,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c } // Check if bounds are fully below or above threshold if (goal.isBounded() && (*upperBound <= goal.thresholdValue() || (*lowerBound >= goal.thresholdValue()))) { - STORM_LOG_INFO("Bisection method determined result after " << iterationCount << " iterations. Found bounds are [" + STORM_PRINT_AND_LOG("Bisection method determined result after " << iterationCount << " iterations. Found bounds are [" << storm::utility::convertNumber(*lowerBound) << ", " << storm::utility::convertNumber(*upperBound) << "], threshold is " << storm::utility::convertNumber(goal.thresholdValue()) << "."); @@ -1094,7 +1094,7 @@ typename internal::ResultReturnType computeViaBisection(Environment c } // check for early termination if (storm::utility::resources::isTerminate()) { - STORM_LOG_WARN("Bisection solver aborted after " << iterationCount << "iterations. Bound difference is " + STORM_PRINT_AND_LOG("Bisection solver aborted after " << iterationCount << "iterations. Bound difference is " << storm::utility::convertNumber(boundDiff) << "."); break; } diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index 7833aa039e..ba8305e1cf 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -40,8 +40,8 @@ ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, conditionalToleranceName, false, "The internally used tolerance for computing conditional probabilities..") .setShortName("condtol") .addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to use.") - .setDefaultValueDouble(1e-04) - .addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorExcluding(0.0, 1.0)) + .setDefaultValueDouble(1e-06) + .addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorIncluding(0.0, 1.0)) .build()) .build()); } From 4e5b17b5d4c27decf5fa0ba15dc99bb4ee2b0c1c Mon Sep 17 00:00:00 2001 From: Sebastian Junges Date: Fri, 23 Jan 2026 20:19:45 +0100 Subject: [PATCH 091/102] a bit extra output --- .../modelchecker/helper/conditional/ConditionalHelper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 14586976b4..0955307d66 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -517,7 +517,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme initStateInReduced = ecElimResult2->oldToNewStateMapping[initStateInReduced]; } - STORM_LOG_INFO("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " + STORM_PRINT_AND_LOG("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " << matrix.getEntryCount() << " transitions."); // Finally, solve the equation system, potentially computing a scheduler @@ -757,7 +757,7 @@ class WeightedReachabilityHelper { initialStateInSubmatrix = ecResult->oldToNewStateMapping[initialStateInSubmatrix]; } isAcyclic = !storm::utility::graph::hasCycle(submatrix); - STORM_LOG_INFO("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " + STORM_PRINT_AND_LOG("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " << submatrix.getEntryCount() << " transitions. Matrix is " << (isAcyclic ? "acyclic." : "cyclic.")); if (computeScheduler) { @@ -1309,7 +1309,7 @@ std::unique_ptr computeConditionalProbabilities(Environment const& if (alg == ConditionalAlgorithmSetting::Default) { alg = ConditionalAlgorithmSetting::Restart; } - STORM_LOG_INFO("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg << "."); + STORM_PRINT_AND_LOG("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg << "."); // sw.restart(); internal::ResultReturnType result{storm::utility::zero()}; switch (alg) { From db266b710222e8af41475275591d70d291e8025d Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sun, 25 Jan 2026 16:17:29 +0100 Subject: [PATCH 092/102] disabled backwards edge to initial when collapsing initial component. --- .../helper/conditional/ConditionalHelper.cpp | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index 463aa2ac5e..a96114d427 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -14,6 +14,7 @@ #include "storm/storage/BitVector.h" #include "storm/storage/MaximalEndComponentDecomposition.h" #include "storm/storage/SparseMatrix.h" +#include "storm/storage/StronglyConnectedComponentDecomposition.h" #include "storm/transformer/EndComponentEliminator.h" #include "storm/utility/Extremum.h" #include "storm/utility/OptionalRef.h" @@ -678,9 +679,6 @@ class WeightedReachabilityHelper { originalToReducedStateIndexMap = subMatrixRowGroups.getNumberOfSetBitsBeforeIndices(); initialStateInSubmatrix = originalToReducedStateIndexMap[initialState]; auto const eliminatedInitialComponentStates = normalForm.maybeStates & ~subMatrixRowGroups; - for (auto state : eliminatedInitialComponentStates) { - originalToReducedStateIndexMap[state] = initialStateInSubmatrix; // map all eliminated states to the initial state - } // build matrix, rows that sum up to 1, target values, condition values storm::storage::SparseMatrixBuilder matrixBuilder(numSubmatrixRows, numSubmatrixRowGroups, 0, true, true, numSubmatrixRowGroups); @@ -693,13 +691,10 @@ class WeightedReachabilityHelper { // Put the row processing into a lambda for avoiding code duplications auto processRow = [&](uint64_t origRowIndex) { - // We make two passes. First, we find out the probability to reach an eliminated initial component state - ValueType const eliminatedInitialComponentProbability = transitionMatrix.getConstrainedRowSum(origRowIndex, eliminatedInitialComponentStates); - // Second, we insert the submatrix entries and find out the target and condition probabilities for this row + // insert the submatrix entries and find out the target and condition probabilities for this row ValueType targetProbability = storm::utility::zero(); ValueType conditionProbability = storm::utility::zero(); bool rowSumIsLess1 = false; - bool initialStateEntryInserted = false; for (auto const& entry : transitionMatrix.getRow(origRowIndex)) { if (normalForm.terminalStates.get(entry.getColumn())) { STORM_LOG_ASSERT(!storm::utility::isZero(entry.getValue()), "Transition probability must be non-zero"); @@ -711,19 +706,11 @@ class WeightedReachabilityHelper { } else { conditionProbability += scaledTargetValue; // for terminal, non-condition states, the condition value equals the target value } - } else if (!eliminatedInitialComponentStates.get(entry.getColumn())) { + } else if (eliminatedInitialComponentStates.get(entry.getColumn())) { + rowSumIsLess1 = true; + } else { auto const columnIndex = originalToReducedStateIndexMap[entry.getColumn()]; - if (!initialStateEntryInserted && columnIndex >= initialStateInSubmatrix) { - if (columnIndex == initialStateInSubmatrix) { - matrixBuilder.addNextValue(currentRow, initialStateInSubmatrix, eliminatedInitialComponentProbability + entry.getValue()); - } else { - matrixBuilder.addNextValue(currentRow, initialStateInSubmatrix, eliminatedInitialComponentProbability); - matrixBuilder.addNextValue(currentRow, columnIndex, entry.getValue()); - } - initialStateEntryInserted = true; - } else { - matrixBuilder.addNextValue(currentRow, columnIndex, entry.getValue()); - } + matrixBuilder.addNextValue(currentRow, columnIndex, entry.getValue()); } } if (rowSumIsLess1) { @@ -898,8 +885,8 @@ class WeightedReachabilityHelper { std::unique_ptr> constructSchedulerForInputModel( std::vector const& schedulerForReducedModel, storm::storage::SparseMatrix const& originalTransitionMatrix, storm::storage::SparseMatrix const& originalBackwardTransitions, NormalFormData const& normalForm) const { - std::vector originalRowToStateIndexMap; // maps original row indices to original state indices. transitionMatrix.getRowGroupIndices() are the - // inverse of that mapping + std::vector originalRowToStateIndexMap; // maps original row indices to original state indices. transitionMatrix.getRowGroupIndices() are + // the inverse of that mapping originalRowToStateIndexMap.reserve(originalTransitionMatrix.getRowCount()); for (uint64_t originalStateIndex = 0; originalStateIndex < originalTransitionMatrix.getRowGroupCount(); ++originalStateIndex) { originalRowToStateIndexMap.insert(originalRowToStateIndexMap.end(), originalTransitionMatrix.getRowGroupSize(originalStateIndex), From 542c1b98eeca6cd77e4e32bcf7babbef8dd72d9d Mon Sep 17 00:00:00 2001 From: Tim Quatmann Date: Sun, 25 Jan 2026 16:38:29 +0100 Subject: [PATCH 093/102] Fix numerical issues with small bisection values and thresholded optimizations. --- .../helper/conditional/ConditionalHelper.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index a96114d427..8821d699e5 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -1178,11 +1178,18 @@ typename internal::ResultReturnType decideThreshold(Environment const } SolutionType val = wrh.computeWeightedDiff(env, direction, storm::utility::one(), -threshold, schedulerRef); - // if val is positive, the conditional probability is (strictly) greater than threshold - // if val is negative, the conditional probability is (strictly) smaller than threshold - // if val is zero, the conditional probability equals the threshold - // so, for the true probability p and comparison ~ we have: p ~ threshold <=> val + threshold ~ threshold - auto finalResult = ResultReturnType(val + threshold); + SolutionType outputProbability; + if (val > storm::utility::zero()) { + // if val is positive, the conditional probability is (strictly) greater than threshold + outputProbability = storm::utility::one(); + } else if (val < storm::utility::zero()) { + // if val is negative, the conditional probability is (strictly) smaller than threshold + outputProbability = storm::utility::zero(); + } else { + // if val is zero, the conditional probability equals the threshold + outputProbability = threshold; + } + auto finalResult = ResultReturnType(outputProbability); if (computeScheduler) { // If requested, construct the scheduler for the original model From 02350c239dc7e068819fa726c2e7279901011996 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 4 Mar 2026 16:59:58 +0100 Subject: [PATCH 094/102] Refactor ExplicitQualitativeCheckResult constructor to use std::optional for scheduler parameter --- .../modelchecker/results/ExplicitQualitativeCheckResult.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 1ca56bc279..8707f463ed 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -42,14 +42,14 @@ ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm: template ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues, - boost::optional>> scheduler) + std::optional>> scheduler) : truthValues(truthValues), scheduler(scheduler) { // Intentionally left empty. } template ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues, - boost::optional>> scheduler) + std::optional>> scheduler) : truthValues(std::move(truthValues)), scheduler(scheduler) { // Intentionally left empty. } From a82759ae27667098653ddf58cb62d542d8016552 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 5 Mar 2026 15:25:30 +0100 Subject: [PATCH 095/102] fix some new location and swich to std::optional --- .../modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp | 6 +++--- .../modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp | 2 +- src/storm/modelchecker/results/CheckResult.cpp | 1 + .../results/ExplicitQualitativeCheckResult.cpp | 7 +++---- .../modelchecker/results/ExplicitQualitativeCheckResult.h | 6 +++--- .../results/ExplicitQuantitativeCheckResult.cpp | 8 ++++---- .../results/ExplicitQuantitativeCheckResult.h | 6 +++--- .../prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 8 ++++---- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp index 3164eeee04..7324d97da1 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp @@ -227,7 +227,7 @@ SparsePcaaQuery::tryAnswerOrNextWeightsAchie if (!optObjIndex.has_value()) { if (!overApproximation->contains(thresholds)) { // The thresholds are not achievable - return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); } referencePoint = thresholds; } else { @@ -247,7 +247,7 @@ SparsePcaaQuery::tryAnswerOrNextWeightsAchie auto optRes = overApproximation->intersection(thresholdPolytope)->optimize(optDirVector); if (!optRes.second) { // The thresholds are not achievable - return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); } referencePoint = thresholds; referencePoint[optObjIndex.value()] = @@ -275,7 +275,7 @@ SparsePcaaQuery::tryAnswerOrNextWeightsAchie return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialStateOfOriginalModel, resultForOriginalModel)); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, true)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, true)); } } diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 8f8fd1f980..394fe5702c 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -325,7 +325,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 0bdd406f21..94c0ed9d26 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -1,6 +1,7 @@ #include "storm/modelchecker/results/CheckResult.h" #include "storm/adapters/RationalFunctionAdapter.h" +#include "storm/adapters/IntervalAdapter.h" #include "storm/modelchecker/results/ExplicitParetoCurveCheckResult.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 8707f463ed..50b9a9e16c 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -1,3 +1,4 @@ +#include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" // Must come first. TODO: fix #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" @@ -286,13 +287,13 @@ void ExplicitQualitativeCheckResult::setScheduler(std::unique_ptr storm::storage::Scheduler const& ExplicitQualitativeCheckResult::getScheduler() const { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template storm::storage::Scheduler& ExplicitQualitativeCheckResult::getScheduler() { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template @@ -337,7 +338,6 @@ template class ExplicitQualitativeCheckResult; template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, std::optional const&) const; -#ifdef STORM_HAVE_CARL template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; @@ -358,7 +358,6 @@ template storm::json ExplicitQualitativeCheckResult::to std::optional const&) const; template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; -#endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 6825f4bce5..95db1271bb 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -30,9 +30,9 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { ExplicitQualitativeCheckResult(vector_type const& truthValues); ExplicitQualitativeCheckResult(vector_type&& truthValues); ExplicitQualitativeCheckResult(boost::variant const& truthValues, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQualitativeCheckResult(boost::variant&& truthValues, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQualitativeCheckResult(ExplicitQualitativeCheckResult const& other) = default; ExplicitQualitativeCheckResult& operator=(ExplicitQualitativeCheckResult const& other) = default; @@ -79,7 +79,7 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { boost::variant truthValues; // An optional scheduler that accompanies the values. - boost::optional>> scheduler; + std::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index ec8222fe09..d775b924e4 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -48,14 +48,14 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(vect template ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boost::variant const& values, - boost::optional>> scheduler) + std::optional>> scheduler) : values(values), scheduler(scheduler) { // Intentionally left empty. } template ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boost::variant&& values, - boost::optional>> scheduler) + std::optional>> scheduler) : values(std::move(values)), scheduler(scheduler) { // Intentionally left empty. } @@ -226,13 +226,13 @@ void ExplicitQuantitativeCheckResult::setScheduler(std::unique_ptr storm::storage::Scheduler const& ExplicitQuantitativeCheckResult::getScheduler() const { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template storm::storage::Scheduler& ExplicitQuantitativeCheckResult::getScheduler() { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index 125752ca14..bf543cd180 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -32,9 +32,9 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult const& values, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQuantitativeCheckResult(boost::variant&& values, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQuantitativeCheckResult(ExplicitQuantitativeCheckResult const& other) = default; ExplicitQuantitativeCheckResult& operator=(ExplicitQuantitativeCheckResult const& other) = default; @@ -85,7 +85,7 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult values; // An optional scheduler that accompanies the values. - boost::optional>> scheduler; + std::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index 1ee43344b7..07369bfbbc 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -16,11 +16,11 @@ std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, @@ -138,7 +138,7 @@ void checkModelForQualitativeResult(std::string const& path, std::string const& ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); for (size_t i = 0; i < expectedResultVector[0].size(); i++) { - EXPECT_EQ(expectedResultVector[0].get(i), result->asExplicitQualitativeCheckResult()[i]); + EXPECT_EQ(expectedResultVector[0].get(i), result->template asExplicitQualitativeCheckResult()[i]); } auto task2 = storm::modelchecker::CheckTask(*formulas[1]); @@ -148,7 +148,7 @@ void checkModelForQualitativeResult(std::string const& path, std::string const& ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); for (size_t i = 0; i < expectedResultVector[1].size(); i++) { - EXPECT_EQ(expectedResultVector[1].get(i), result->asExplicitQualitativeCheckResult()[i]); + EXPECT_EQ(expectedResultVector[1].get(i), result->template asExplicitQualitativeCheckResult()[i]); } } From f07309c5c00dc83790bb0d84d57f3262ef7bae68 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 5 Mar 2026 15:29:43 +0100 Subject: [PATCH 096/102] format --- src/storm/modelchecker/results/CheckResult.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 94c0ed9d26..f6c6827c0b 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -1,7 +1,7 @@ #include "storm/modelchecker/results/CheckResult.h" -#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/modelchecker/results/ExplicitParetoCurveCheckResult.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" From 4be794c5a5964b10c2271b67c16a845cabd251a7 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 6 Mar 2026 10:46:55 +0100 Subject: [PATCH 097/102] Update ExplicitQualitativeCheckResult usage to use SolutionType and include IntervalForward in tests --- src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp | 4 ++-- .../prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 394fe5702c..39c60fea41 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -153,8 +153,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index 07369bfbbc..2cb9f531a3 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -1,4 +1,5 @@ #include "storm-config.h" +#include "storm/adapters/IntervalForward.h" #include "test/storm_gtest.h" #include "storm-parsers/api/model_descriptions.h" From 7e57f56b2dee2a778574db5b28ed31543d77c486 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 6 Mar 2026 11:20:47 +0100 Subject: [PATCH 098/102] Fix other qualitative check result value types --- .../prctl/SparseDtmcPrctlModelChecker.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 39c60fea41..e54a69b4ef 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -108,8 +108,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c "Formula needs to have discrete upper step bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -129,7 +129,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); @@ -171,7 +171,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -192,7 +192,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -213,7 +213,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -308,7 +308,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c "Computing rewards on uncertain model requires graph-preservation."); } std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards( @@ -380,13 +380,13 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto values = helper.computeLongRunAverageProbabilities(env, subResult.getTruthValuesVector()); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(values))); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(values))); } } @@ -418,8 +418,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities( @@ -443,8 +443,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asReachabilityRewardFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards( From 94cb86402c6dc84af8b06fc9332557b5cdc82d75 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 6 Mar 2026 11:53:06 +0100 Subject: [PATCH 099/102] format --- .../GenerateMonitorVerifierSettings.cpp | 10 +++--- .../modelchecker/ModelCheckerEnvironment.cpp | 3 +- .../modelchecker/ModelCheckerEnvironment.h | 2 +- .../helper/conditional/ConditionalHelper.cpp | 36 ++++++++++--------- .../settings/modules/ModelCheckerSettings.cpp | 16 ++++----- .../settings/modules/ModelCheckerSettings.h | 2 +- src/storm/storage/SparseMatrix.cpp | 1 - src/storm/transformer/AddUncertainty.cpp | 5 +-- src/storm/transformer/AddUncertainty.h | 3 +- 9 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp b/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp index 37921d03a6..e2baab8be1 100644 --- a/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp +++ b/src/storm-pomdp-cli/settings/modules/GenerateMonitorVerifierSettings.cpp @@ -6,10 +6,8 @@ namespace modules { const std::string GenerateMonitorVerifierSettings::moduleName = "generateMonitorVerifier"; -GenerateMonitorVerifierSettings::GenerateMonitorVerifierSettings() : ModuleSettings(moduleName) { +GenerateMonitorVerifierSettings::GenerateMonitorVerifierSettings() : ModuleSettings(moduleName) {} -} - -} -} -} +} // namespace modules +} // namespace settings +} // namespace storm diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp index 5c8efb8333..d0ecb5c347 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.cpp @@ -49,9 +49,8 @@ void ModelCheckerEnvironment::setConditionalTolerance(storm::RationalNumber cons conditionalToleranceSetting = value; } - storm::RationalNumber ModelCheckerEnvironment::getConditionalTolerance() const { - return conditionalToleranceSetting; + return conditionalToleranceSetting; } bool ModelCheckerEnvironment::isAllowOptimizationForBoundedPropertiesSet() const { diff --git a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h index 8cd86c06c9..b011b37a0b 100644 --- a/src/storm/environment/modelchecker/ModelCheckerEnvironment.h +++ b/src/storm/environment/modelchecker/ModelCheckerEnvironment.h @@ -4,11 +4,11 @@ #include #include +#include "storm/adapters/RationalNumberAdapter.h" #include "storm/environment/Environment.h" #include "storm/environment/SubEnvironment.h" #include "storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h" #include "storm/modelchecker/helper/infinitehorizon/SteadyStateDistributionAlgorithm.h" -#include "storm/adapters/RationalNumberAdapter.h" namespace storm { diff --git a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp index dcd569fc2b..9cf9cdf09f 100644 --- a/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp +++ b/src/storm/modelchecker/helper/conditional/ConditionalHelper.cpp @@ -519,7 +519,7 @@ typename internal::ResultReturnType computeViaRestartMethod(Environme } STORM_PRINT_AND_LOG("Processed model has " << matrix.getRowGroupCount() << " states and " << matrix.getRowGroupCount() << " choices and " - << matrix.getEntryCount() << " transitions."); + << matrix.getEntryCount() << " transitions."); // Finally, solve the equation system, potentially computing a scheduler std::optional> reducedSchedulerChoices; @@ -745,7 +745,7 @@ class WeightedReachabilityHelper { } isAcyclic = !storm::utility::graph::hasCycle(submatrix); STORM_PRINT_AND_LOG("Processed model has " << submatrix.getRowGroupCount() << " states and " << submatrix.getRowGroupCount() << " choices and " - << submatrix.getEntryCount() << " transitions. Matrix is " << (isAcyclic ? "acyclic." : "cyclic.")); + << submatrix.getEntryCount() << " transitions. Matrix is " << (isAcyclic ? "acyclic." : "cyclic.")); if (computeScheduler) { // For easier conversion of schedulers to the original model, we create and update some index mappings @@ -1060,8 +1060,8 @@ typename internal::ResultReturnType computeViaBisection(Environment c } if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) { STORM_PRINT_AND_LOG("Bisection method converged after " << iterationCount << " iterations. Difference is " - << std::setprecision(std::numeric_limits::digits10) - << storm::utility::convertNumber(boundDiff) << "."); + << std::setprecision(std::numeric_limits::digits10) + << storm::utility::convertNumber(boundDiff) << "."); break; } else if (usePolicyTracking && lowerScheduler && upperScheduler && (*lowerScheduler == *upperScheduler)) { STORM_PRINT_AND_LOG("Bisection method converged after " << iterationCount << " iterations due to identical schedulers for lower and upper bound."); @@ -1074,15 +1074,15 @@ typename internal::ResultReturnType computeViaBisection(Environment c // Check if bounds are fully below or above threshold if (goal.isBounded() && (*upperBound <= goal.thresholdValue() || (*lowerBound >= goal.thresholdValue()))) { STORM_PRINT_AND_LOG("Bisection method determined result after " << iterationCount << " iterations. Found bounds are [" - << storm::utility::convertNumber(*lowerBound) << ", " - << storm::utility::convertNumber(*upperBound) << "], threshold is " - << storm::utility::convertNumber(goal.thresholdValue()) << "."); + << storm::utility::convertNumber(*lowerBound) << ", " + << storm::utility::convertNumber(*upperBound) << "], threshold is " + << storm::utility::convertNumber(goal.thresholdValue()) << "."); break; } // check for early termination if (storm::utility::resources::isTerminate()) { STORM_PRINT_AND_LOG("Bisection solver aborted after " << iterationCount << "iterations. Bound difference is " - << storm::utility::convertNumber(boundDiff) << "."); + << storm::utility::convertNumber(boundDiff) << "."); break; } // process the middle value for the next iteration @@ -1267,14 +1267,15 @@ std::unique_ptr computeConditionalProbabilities(Environment const& auto normalFormConstructionEnv = env; auto analysisEnv = env; -// if (env.solver().isForceSoundness()) { -// // We intuitively have to divide the precision into two parts, one for computations when constructing the normal form and one for the actual analysis. -// // As the former is usually less numerically challenging, we use a factor of 1/10 for the normal form construction and 9/10 for the analysis. -// auto const normalFormPrecisionFactor = storm::utility::convertNumber("1/10"); -// normalFormConstructionEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * normalFormPrecisionFactor); -// analysisEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * -// (storm::utility::one() - normalFormPrecisionFactor)); -// } + // if (env.solver().isForceSoundness()) { + // // We intuitively have to divide the precision into two parts, one for computations when constructing the normal form and one for the actual + // analysis. + // // As the former is usually less numerically challenging, we use a factor of 1/10 for the normal form construction and 9/10 for the analysis. + // auto const normalFormPrecisionFactor = storm::utility::convertNumber("1/10"); + // normalFormConstructionEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * normalFormPrecisionFactor); + // analysisEnv.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * + // (storm::utility::one() - normalFormPrecisionFactor)); + // } // We first translate the problem into a normal form. // @see doi.org/10.1007/978-3-642-54862-8_43 @@ -1303,7 +1304,8 @@ std::unique_ptr computeConditionalProbabilities(Environment const& if (alg == ConditionalAlgorithmSetting::Default) { alg = ConditionalAlgorithmSetting::Restart; } - STORM_PRINT_AND_LOG("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg << "."); + STORM_PRINT_AND_LOG("Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() << " maybe states using algorithm '" << alg + << "."); // sw.restart(); internal::ResultReturnType result{storm::utility::zero()}; switch (alg) { diff --git a/src/storm/settings/modules/ModelCheckerSettings.cpp b/src/storm/settings/modules/ModelCheckerSettings.cpp index ba8305e1cf..8a79ee6907 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.cpp +++ b/src/storm/settings/modules/ModelCheckerSettings.cpp @@ -15,7 +15,6 @@ const std::string ModelCheckerSettings::ltl2daToolOptionName = "ltl2datool"; const std::string ModelCheckerSettings::conditionalAlgorithmOptionName = "conditional"; static const std::string conditionalToleranceName = "conditional-tolerance"; - ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, filterRewZeroOptionName, false, "If set, states with reward zero are filtered out, potentially reducing the size of the equation system") @@ -37,13 +36,14 @@ ModelCheckerSettings::ModelCheckerSettings() : ModuleSettings(moduleName) { .build()) .build()); // Would be better if there was a createRationalArgument . - this->addOption(storm::settings::OptionBuilder(moduleName, conditionalToleranceName, false, "The internally used tolerance for computing conditional probabilities..") - .setShortName("condtol") - .addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to use.") - .setDefaultValueDouble(1e-06) - .addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorIncluding(0.0, 1.0)) - .build()) - .build()); + this->addOption( + storm::settings::OptionBuilder(moduleName, conditionalToleranceName, false, "The internally used tolerance for computing conditional probabilities..") + .setShortName("condtol") + .addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to use.") + .setDefaultValueDouble(1e-06) + .addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorIncluding(0.0, 1.0)) + .build()) + .build()); } bool ModelCheckerSettings::isFilterRewZeroSet() const { diff --git a/src/storm/settings/modules/ModelCheckerSettings.h b/src/storm/settings/modules/ModelCheckerSettings.h index 70fc7b43a5..ef31a110b8 100644 --- a/src/storm/settings/modules/ModelCheckerSettings.h +++ b/src/storm/settings/modules/ModelCheckerSettings.h @@ -1,9 +1,9 @@ #pragma once #include "storm-config.h" +#include "storm/adapters/RationalNumberAdapter.h" #include "storm/modelchecker/helper/conditional/ConditionalAlgorithmSetting.h" #include "storm/settings/modules/ModuleSettings.h" -#include "storm/adapters/RationalNumberAdapter.h" namespace storm { namespace settings { diff --git a/src/storm/storage/SparseMatrix.cpp b/src/storm/storage/SparseMatrix.cpp index 0600f72061..3d617f5752 100644 --- a/src/storm/storage/SparseMatrix.cpp +++ b/src/storm/storage/SparseMatrix.cpp @@ -688,7 +688,6 @@ typename SparseMatrix::index_type SparseMatrix::getRowEntr return (this->rowIndications[row + 1] - this->rowIndications[row]); } - template typename SparseMatrix::index_type SparseMatrix::getNonzeroEntryCount() const { return nonzeroEntryCount; diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index e62388a048..a571208c97 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -17,14 +17,15 @@ template AddUncertainty::AddUncertainty(std::shared_ptr> const& originalModel) : origModel(originalModel) {} template -std::shared_ptr> AddUncertainty::transform(double additiveUncertainty, double minimalTransitionProbability, uint64_t maxSuccessors) { +std::shared_ptr> AddUncertainty::transform(double additiveUncertainty, double minimalTransitionProbability, + uint64_t maxSuccessors) { // we first build the matrix and later copy the row grouping. auto newMatrixBuilder = storage::SparseMatrixBuilder(origModel->getTransitionMatrix().getRowCount(), origModel->getTransitionMatrix().getColumnCount(), origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); // Build transition matrix (without row grouping) for (uint64_t rowIndex = 0; rowIndex < origModel->getTransitionMatrix().getRowCount(); ++rowIndex) { - if (origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors) { + if (origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors) { for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), additiveUncertainty, minimalTransitionProbability)); } diff --git a/src/storm/transformer/AddUncertainty.h b/src/storm/transformer/AddUncertainty.h index e5f0f4fab7..7e0ae97986 100644 --- a/src/storm/transformer/AddUncertainty.h +++ b/src/storm/transformer/AddUncertainty.h @@ -16,7 +16,8 @@ template class AddUncertainty { public: AddUncertainty(std::shared_ptr> const& originalModel); - std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001, uint64_t maxSuccessors = 10000000); + std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001, + uint64_t maxSuccessors = 10000000); private: storm::Interval addUncertainty(ValueType const& vt, double additiveUncertainty, double minimalValue); From 5acfab72f89ba63442ab57cb7349bda411090a37 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 6 Mar 2026 17:52:35 +0100 Subject: [PATCH 100/102] Fix almost all build problems --- .../generator/GenerateMonitorVerifier.cpp | 8 +++--- .../generator/GenerateMonitorVerifier.h | 2 +- src/storm/io/DirectEncodingExporter.cpp | 2 ++ ...ndeterministicStepBoundedHorizonHelper.cpp | 6 ++-- .../prctl/SparseMdpPrctlModelChecker.cpp | 23 ++++++++------- .../prctl/SparseMdpPrctlModelChecker.h | 18 +----------- .../SparseMdpEndComponentInformation.cpp | 4 +-- .../prctl/helper/SparseMdpPrctlHelper.cpp | 28 +++++++++---------- src/storm/models/sparse/Model.cpp | 2 +- .../IterativeMinMaxLinearEquationSolver.cpp | 25 ++++++++--------- src/storm/solver/LinearEquationSolver.cpp | 2 +- .../solver/MinMaxLinearEquationSolver.cpp | 6 ++-- .../solver/helper/ValueIterationOperator.cpp | 2 +- .../solver/helper/ValueIterationOperator.h | 2 +- src/storm/solver/multiplier/Multiplier.cpp | 19 ++++++------- src/storm/solver/multiplier/Multiplier.h | 7 +++-- .../multiplier/ViOperatorMultiplier.cpp | 1 + src/storm/utility/NumberTraits.h | 7 +++++ 18 files changed, 78 insertions(+), 86 deletions(-) diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp index bd684495ba..1cd6584c44 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.cpp @@ -61,7 +61,7 @@ std::shared_ptr> GenerateMonitorVerifier:: // Build choice label map of monitor choices std::vector monitorChoiceLabels; - for (auto i = 0; i < monitor.getTransitionMatrix().getRowCount(); i++) { + for (typename storm::storage::SparseMatrix::index_type i = 0; i < monitor.getTransitionMatrix().getRowCount(); i++) { auto const& monitorLabels = monitor.getChoiceLabeling().getLabelsOfChoice(i); STORM_LOG_THROW(monitorLabels.size() == 1, storm::exceptions::InvalidArgumentException, "Monitor choice has not exactly one choice label"); monitorChoiceLabels.push_back(*monitorLabels.begin()); @@ -343,7 +343,7 @@ std::shared_ptr> GenerateMonitorVerifier:: svBuilder.addVariable(monvar); svBuilder.addVariable(mcvar); std::set variables; - for (auto i = 0; i < mc.getNumberOfStates(); i++) { + for (uint_fast64_t i = 0; i < mc.getNumberOfStates(); i++) { const auto& valAssignment = mc.getStateValuations().at(i); for (auto val = valAssignment.begin(); val != valAssignment.end(); ++val) { if (val.isVariableAssignment() && !variables.contains(val.getVariable())) { @@ -353,8 +353,8 @@ std::shared_ptr> GenerateMonitorVerifier:: } } - for (auto i = 0; i < mc.getNumberOfStates(); i++) { - for (auto j = 0; j < monitor.getNumberOfStates(); j++) { + for (uint_fast64_t i = 0; i < mc.getNumberOfStates(); i++) { + for (uint_fast64_t j = 0; j < monitor.getNumberOfStates(); j++) { product_state_type s(i, j); if (!prodToIndexMap.contains(s)) continue; diff --git a/src/storm-pomdp/generator/GenerateMonitorVerifier.h b/src/storm-pomdp/generator/GenerateMonitorVerifier.h index cf925d33e6..7fcd1b868f 100644 --- a/src/storm-pomdp/generator/GenerateMonitorVerifier.h +++ b/src/storm-pomdp/generator/GenerateMonitorVerifier.h @@ -43,8 +43,8 @@ class GenerateMonitorVerifier { private: const storm::models::sparse::Dtmc& mc; const storm::models::sparse::Mdp& monitor; - std::shared_ptr& exprManager; std::vector risk; + std::shared_ptr& exprManager; storm::expressions::Variable monvar; storm::expressions::Variable mcvar; Options options; diff --git a/src/storm/io/DirectEncodingExporter.cpp b/src/storm/io/DirectEncodingExporter.cpp index 2fb47329d4..26679ca7f0 100644 --- a/src/storm/io/DirectEncodingExporter.cpp +++ b/src/storm/io/DirectEncodingExporter.cpp @@ -72,6 +72,8 @@ void explicitExportSparseModel(std::ostream& os, std::shared_ptr) { os << "double-interval"; + } else if constexpr (std::is_same_v) { + os << "rational-interval"; } else if constexpr (std::is_same_v) { os << "parametric"; } else { diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp index b3739fe0c3..9eedacca02 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp @@ -1,4 +1,6 @@ #include "storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h" +#include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/adapters/RationalNumberForward.h" #include "storm/modelchecker/hints/ExplicitModelCheckerHint.h" @@ -61,7 +63,7 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper b; uint64_t subresultSize; - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { // For intervals, we cannot remove all non maybe states as that would lead to the upper probability of rows summing to below 1. // Instead we only drop all outgoing transitions of non maybe states. // See src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp:624 for more details. @@ -88,7 +90,7 @@ std::vector SparseNondeterministicStepBoundedHorizonHelperrepeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound - lowerBound + 1); storm::storage::SparseMatrix submatrix; - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates)); } else { submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index ed657bae30..55c4102e46 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -37,7 +37,7 @@ template bool SparseMdpPrctlModelChecker::canHandleStatic(CheckTask const& checkTask, bool* requiresSingleInitialState) { storm::logic::Formula const& formula = checkTask.getFormula(); - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { if (formula.isInFragment(storm::logic::propositional())) { return true; } @@ -118,7 +118,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); if (pathFormula.isMultiDimensional() || pathFormula.getTimeBoundReference().isRewardBound()) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented multi dimensional bounded until with intervals"); return nullptr; } else { @@ -143,7 +143,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); - storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; + storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), @@ -151,7 +151,6 @@ std::unique_ptr SparseMdpPrctlModelChecker::com return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } } -} template std::unique_ptr SparseMdpPrctlModelChecker::computeNextProbabilities( @@ -208,7 +207,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeHOAPathProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented automata-props with intervals"); } else { storm::logic::HOAPathFormula const& pathFormula = checkTask.getFormula(); @@ -235,7 +234,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLTLProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented LTL with intervals"); } else { storm::logic::PathFormula const& pathFormula = checkTask.getFormula(); @@ -280,7 +279,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { return storm::modelchecker::computeConditionalProbabilities( @@ -437,7 +436,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented LRA probabilities with intervals"); } else { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); @@ -462,7 +461,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageRewards( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lra with intervals"); } else { STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, @@ -483,7 +482,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::checkMultiObjectiveFormula( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented multi-objective with intervals"); } else { return multiobjective::performMultiObjectiveModelChecking(env, this->getModel(), checkTask.getFormula(), checkTask.isProduceSchedulersSet()); @@ -493,7 +492,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template std::unique_ptr SparseMdpPrctlModelChecker::checkLexObjectiveFormula( const Environment& env, const CheckTask& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { @@ -508,7 +507,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template std::unique_ptr SparseMdpPrctlModelChecker::checkQuantileFormula( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented quantile formulas with intervals"); } else { STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h index d0ddf9168c..5a7f10a1fe 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h @@ -11,26 +11,10 @@ class Environment; namespace modelchecker { template class SparseMdpPrctlModelChecker : public SparsePropositionalModelChecker { - private: - template - struct GetSolutionType { - using type = T; - }; - - template - struct GetSolutionType { - using type = double; - }; - - template - struct GetSolutionType { - using type = storm::RationalNumber; - }; - public: typedef typename SparseMdpModelType::ValueType ValueType; typedef typename SparseMdpModelType::RewardModelType RewardModelType; - using SolutionType = typename GetSolutionType::type; + using SolutionType = storm::IntervalBaseType; explicit SparseMdpPrctlModelChecker(SparseMdpModelType const& model); diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp index ba7e73fabc..a90c6be484 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp @@ -105,7 +105,7 @@ SparseMdpEndComponentInformation SparseMdpEndComponentInformation* columnSumVector, std::vector* summandResultVector, bool gatherExitChoices) { SparseMdpEndComponentInformation result(endComponentDecomposition, maybeStates); // TODO: Just like SparseMdpPrctlHelper::computeFixedPointSystemUntilProbabilities, this method must be adapted for intervals. - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support the elimination of end components and the creation of an adequate equation system with interval models."); } @@ -247,7 +247,7 @@ SparseMdpEndComponentInformation SparseMdpEndComponentInformation& submatrix, std::vector& subvector, bool gatherExitChoices) { SparseMdpEndComponentInformation result(endComponentDecomposition, maybeStates); // TODO: Just like SparseMdpPrctlHelper::computeFixedPointSystemUntilProbabilities, this method must be adapted for intervals. - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support the elimination of end components and the creation of an adequate equation system with interval models."); } diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index f4b76af4a4..8f78376274 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -43,7 +43,7 @@ template std::map SparseMdpPrctlHelper::computeRewardBoundedValues( Environment const& env, OptimizationDirection dir, rewardbounded::MultiDimensionalRewardUnfolding& rewardUnfolding, storm::storage::BitVector const& initialStates) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reward bounded values with interval models."); } else { storm::utility::Stopwatch swAll(true), swBuild, swCheck; @@ -133,7 +133,7 @@ template std::vector SparseMdpPrctlHelper::computeNextProbabilities( Environment const& env, OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with interval models."); } else { // Create the vector with which to multiply and initialize it correctly. @@ -612,7 +612,7 @@ void computeFixedPointSystemUntilProbabilities(storm::solver::SolveGoal const& transitionMatrix, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix& submatrix, std::vector& b) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { // For non-interval based models, we can eliminate the rows and columns from the original transition probability matrix for states // whose probabilities are already known... However, there is information in the transition to those states. // Thus, we cannot eliminate them all. @@ -757,7 +757,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support this end component with interval models."); } else { ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); @@ -768,7 +768,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper && !std::is_same_v) { + if constexpr (!storm::IsIntervalType) { // For non-interval models, we only operated on the maybe states, and we must recover the qualitative values for the other state. storm::utility::vector::setVectorValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); } else { @@ -777,7 +777,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper>(*scheduler, resultForMaybeStates.getScheduler(), + extractSchedulerChoices>(*scheduler, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates); } } @@ -833,7 +833,7 @@ template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support instantenous rewards with interval models."); } else { // Only compute the result if the model has a state-based reward this->getModel(). @@ -854,7 +854,7 @@ template std::vector SparseMdpPrctlHelper::computeCumulativeRewards( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support cumulative rewards with interval models."); } else { // Only compute the result if the model has at least one reward this->getModel(). @@ -1383,7 +1383,7 @@ template void computeUpperRewardBounds(SparseMdpHintType& hintInformation, storm::OptimizationDirection const& direction, storm::storage::SparseMatrix const& submatrix, std::vector const& choiceRewards, std::vector const& oneStepTargetProbabilities) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing upper reward bounds with interval models."); } else { // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17). @@ -1422,7 +1422,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper> scheduler; if (produceScheduler) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support producing schedulers in this function with interval models."); } else { scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); @@ -1467,7 +1467,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper> ecInformation; if (hintInformation.getEliminateEndComponents()) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models."); } else { ecInformation = computeFixedPointSystemReachabilityRewardsEliminateEndComponents( @@ -1492,7 +1492,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models."); } else { ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); @@ -1523,7 +1523,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelperisDeterministicScheduler(), "Expected a deterministic scheduler"); STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler"); - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { return MDPSparseModelCheckingHelperReturnType(std::move(result)); } else { return MDPSparseModelCheckingHelperReturnType(std::move(result), std::move(scheduler)); @@ -1535,7 +1535,7 @@ std::unique_ptr SparseMdpPrctlHelper::comp Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional probabilities with interval models."); } else { std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); diff --git a/src/storm/models/sparse/Model.cpp b/src/storm/models/sparse/Model.cpp index 8d6c17003c..f283bfaa90 100644 --- a/src/storm/models/sparse/Model.cpp +++ b/src/storm/models/sparse/Model.cpp @@ -644,7 +644,7 @@ bool Model::supportsParameters() const { template bool Model::supportsUncertainty() const { - return std::is_same_v || std::is_same_v; + return storm::IsIntervalType; } template diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp index 8ecbb561e4..32040e68ec 100644 --- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp @@ -136,7 +136,7 @@ void IterativeMinMaxLinearEquationSolver::setUpViOperat // The trivial row grouping minmax operator makes sense over intervals. viOperatorTriv = std::make_shared>(); viOperatorTriv->setMatrixBackwards(*this->A); - if constexpr (!std::is_same_v and !std::is_same_v) { + if constexpr (!storm::IsIntervalType) { // It might be that someone is using a minmaxlinearequationsolver with an advanced VI algorithm // but is just passing a DTMC over doubles. In this case we need to populate this VI operator. // It behaves exactly the same as the trivial row grouping operator, but it is currently hardcoded @@ -202,8 +202,7 @@ void IterativeMinMaxLinearEquationSolver::extractSchedu setUpViOperator(); } if (viOperatorTriv) { - if constexpr (std::is_same() && std::is_same() || - std::is_same_v && std::is_same_v) { + if constexpr (storm::IsIntervalType && storm::IsIntervalType) { storm::solver::helper::SchedulerTrackingHelper schedHelper(viOperatorTriv); schedHelper.computeScheduler(x, b, dir, *this->schedulerChoices, uncertaintyResolutionMode, updateX ? &x : nullptr, this->robustSchedulerIndex); } else { @@ -220,8 +219,8 @@ template bool IterativeMinMaxLinearEquationSolver::solveInducedEquationSystem( Environment const& env, std::unique_ptr>& linearEquationSolver, std::vector const& scheduler, std::vector& x, std::vector& subB, std::vector const& originalB, OptimizationDirection dir) const { - if constexpr (std::is_same_v || std::is_same_v) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement solving induced equation systems for interval-based models outside of robust VI."); // Implementing this requires linear equation systems with different value types and solution types (or some appropriate casting) @@ -336,7 +335,7 @@ template bool IterativeMinMaxLinearEquationSolver::performPolicyIteration( Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b, std::vector&& initialPolicy) const { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement policy iteration for interval-based models."); return false; } else { @@ -462,7 +461,7 @@ MinMaxLinearEquationSolverRequirements IterativeMinMaxLinearEquationSolver || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ASSERT(!needsLinEqSolver, "Intervals should not require a linear equation solver."); // nothing to be done; } else if (needsLinEqSolver) { @@ -563,7 +562,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsOptimisticValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement optimistic value iteration for interval-based models."); return false; } else { @@ -619,7 +618,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsGuessingValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement guessing value iteration for interval-based models."); return false; } else { @@ -786,7 +785,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsIntervalIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement interval iteration for interval-based models"); return false; } else { @@ -829,7 +828,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsSoundValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "SoundVI does not handle interval-based models"); return false; } else { @@ -881,7 +880,7 @@ bool IterativeMinMaxLinearEquationSolver::solveEquation template bool IterativeMinMaxLinearEquationSolver::solveEquationsViToPi(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "ViToPi does not handle interval-based models"); return false; } @@ -916,7 +915,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsRationalSearch(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Rational search does not handle interval-based models"); return false; } else { diff --git a/src/storm/solver/LinearEquationSolver.cpp b/src/storm/solver/LinearEquationSolver.cpp index 3ee696adde..3ad3d168d9 100644 --- a/src/storm/solver/LinearEquationSolver.cpp +++ b/src/storm/solver/LinearEquationSolver.cpp @@ -148,7 +148,7 @@ template std::unique_ptr> GeneralLinearEquationSolverFactory::create(Environment const& env) const { EquationSolverType type = env.solver().getLinearEquationSolverType(); - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not implemented interval-based linear equation solvers"); } diff --git a/src/storm/solver/MinMaxLinearEquationSolver.cpp b/src/storm/solver/MinMaxLinearEquationSolver.cpp index 09e1668a95..5ee11d5e9a 100644 --- a/src/storm/solver/MinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/MinMaxLinearEquationSolver.cpp @@ -252,19 +252,19 @@ std::unique_ptr> GeneralMinM result = std::make_unique>( std::make_unique>()); } else if (method == MinMaxMethod::Topological) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ERROR("Topological method not implemented for ValueType==Interval."); } else { result = std::make_unique>(); } } else if (method == MinMaxMethod::LinearProgramming || method == MinMaxMethod::ViToLp) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ERROR("LP method not implemented for ValueType==Interval."); } else { result = std::make_unique>(storm::utility::solver::getLpSolverFactory()); } } else if (method == MinMaxMethod::Acyclic) { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ERROR("Acyclic method not implemented for ValueType==Interval"); } else { result = std::make_unique>(); diff --git a/src/storm/solver/helper/ValueIterationOperator.cpp b/src/storm/solver/helper/ValueIterationOperator.cpp index a980880c70..44dbc87aa0 100644 --- a/src/storm/solver/helper/ValueIterationOperator.cpp +++ b/src/storm/solver/helper/ValueIterationOperator.cpp @@ -53,7 +53,7 @@ void ValueIterationOperator::setMat matrixColumns.back() = StartOfRowGroupIndicator; // This is the start of the next row group } } else { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { matrixColumns.push_back(StartOfRowIndicator); // Indicate start of first row for (auto rowIndex : indexRange(0, numRows)) { bool hasOnlyConstants = true; diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index c20dea1518..a3172ad40e 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -282,7 +282,7 @@ class ValueIterationOperator { template auto applyRow(std::vector::const_iterator& matrixColumnIt, typename std::vector::const_iterator& matrixValueIt, OperandType const& operand, OffsetType const& offsets, uint64_t offsetIndex) const { - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (storm::IsIntervalType) { return applyRowRobust(matrixColumnIt, matrixValueIt, operand, offsets, offsetIndex); } else { return applyRowStandard(matrixColumnIt, matrixValueIt, operand, offsets, offsetIndex); diff --git a/src/storm/solver/multiplier/Multiplier.cpp b/src/storm/solver/multiplier/Multiplier.cpp index 8f7e5868ec..7b30a6afca 100644 --- a/src/storm/solver/multiplier/Multiplier.cpp +++ b/src/storm/solver/multiplier/Multiplier.cpp @@ -76,14 +76,14 @@ void Multiplier::repeatedMultiplyAndReduce(Environment template void Multiplier::repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, - std::vector& x, std::vector const* b, uint64_t n, - ValueType factor) const { + std::vector& x, std::vector const* b, uint64_t n, + SolutionType factor) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); for (uint64_t i = 0; i < n; ++i) { progress.updateProgress(i); - std::transform(x.begin(), x.end(), x.begin(), [factor](ValueType& c) { return c * factor; }); + std::transform(x.begin(), x.end(), x.begin(), [factor](SolutionType& c) { return c * factor; }); multiplyAndReduce(env, dir, x, b, x); if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Aborting after " << i << " of " << n << " multiplications"); @@ -93,14 +93,14 @@ void Multiplier::repeatedMultiplyAndReduceWithFactor(En } template -void Multiplier::repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, - uint64_t n, ValueType factor) const { +void Multiplier::repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, + uint64_t n, SolutionType factor) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); for (uint64_t i = 0; i < n; ++i) { progress.updateProgress(i); - std::transform(x.begin(), x.end(), x.begin(), [factor](ValueType& c) { return c * factor; }); + std::transform(x.begin(), x.end(), x.begin(), [factor](SolutionType& c) { return c * factor; }); multiply(env, x, b, x); if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Aborting after " << i << " of " << n << " multiplications"); @@ -126,17 +126,14 @@ std::unique_ptr> MultiplierFactory || (std::is_same_v && std::is_same_v) || - (std::is_same_v && std::is_same_v))) { + (std::is_same_v || (storm::IsIntervalType && storm::IsIntervalType))) { STORM_LOG_INFO("Switching multiplier type from 'vioperator' to 'native' because the given ValueType is not supported by the VI Operator multiplier."); type = MultiplierType::Native; } switch (type) { case MultiplierType::ViOperator: - if constexpr (std::is_same_v || - (std::is_same_v && std::is_same_v) || - (std::is_same_v && std::is_same_v)) { + if constexpr (std::is_same_v || (storm::IsIntervalType && storm::IsIntervalType)) { throw storm::exceptions::NotImplementedException() << "VI Operator multiplier not supported with given value type."; } if (matrix.hasTrivialRowGrouping()) { diff --git a/src/storm/solver/multiplier/Multiplier.h b/src/storm/solver/multiplier/Multiplier.h index 6f29910346..3a8bccd009 100644 --- a/src/storm/solver/multiplier/Multiplier.h +++ b/src/storm/solver/multiplier/Multiplier.h @@ -134,7 +134,8 @@ class Multiplier { * @param n The number of times to perform the multiplication. * @param factor The scalar to multiply with in each iteration. */ - void repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, uint64_t n, ValueType factor) const; + void repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, uint64_t n, + SolutionType factor) const; /*! * Performs repeated matrix-vector multiplication x' = A*(factor * x) + b, minimizes/maximizes over the row groups @@ -150,8 +151,8 @@ class Multiplier { * @param n The number of times to perform the multiplication. * @param factor The scalar to multiply with in each iteration. */ - void repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, uint64_t n, ValueType factor) const; + void repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, std::vector& x, + std::vector const* b, uint64_t n, SolutionType factor) const; protected: std::vector& provideCachedVector(uint64_t size) const; diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp index a2ff3f3d43..fc85ce4cd1 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp @@ -1,5 +1,6 @@ #include "ViOperatorMultiplier.h" +#include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/exceptions/NotSupportedException.h" #include "storm/solver/helper/ValueIterationOperator.h" diff --git a/src/storm/utility/NumberTraits.h b/src/storm/utility/NumberTraits.h index d37abdc3a4..408471dfa6 100644 --- a/src/storm/utility/NumberTraits.h +++ b/src/storm/utility/NumberTraits.h @@ -1,5 +1,6 @@ #pragma once +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalFunctionForward.h" #include "storm/adapters/RationalNumberForward.h" @@ -40,6 +41,12 @@ struct NumberTraits { }; #endif +template<> +struct NumberTraits { + static const bool SupportsExponential = false; + static const bool IsExact = false; +}; + template<> struct NumberTraits { static const bool SupportsExponential = false; From d0cf6f00f74cabfa24d7a182c61ee6523a4242f6 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 10 Mar 2026 11:45:00 +0100 Subject: [PATCH 101/102] Add support for interval value types in model processing and verification engines --- src/storm-cli-utilities/model-handling.h | 66 +++++++++++++++++------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index ad1673b286..2394c58bcc 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -278,6 +278,12 @@ inline ModelProcessingInformation getModelProcessingInformation(SymbolicInput co case ModelProcessingInformation::ValueType::FinitePrecision: return storm::utility::canHandle( mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); + case ModelProcessingInformation::ValueType::FinitePrecisionInterval: + return storm::utility::canHandle( + mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); + case ModelProcessingInformation::ValueType::ExactInterval: + return storm::utility::canHandle( + mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); } return false; }; @@ -389,6 +395,10 @@ auto applyValueType(ModelProcessingInformation::ValueType vt, auto const& callba return callback.template operator()(); case Parametric: return callback.template operator()(); + case FinitePrecisionInterval: + return callback.template operator()(); + case ExactInterval: + return callback.template operator()(); } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unexpected value type."); } @@ -408,6 +418,10 @@ auto applyDdLibValueType(storm::dd::DdType dd, ModelProcessingInformation::Value return callback.template operator()(); case Parametric: return callback.template operator()(); + case FinitePrecisionInterval: + return callback.template operator()(); + case ExactInterval: + return callback.template operator()(); } } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unexpected DDType or value type."); @@ -599,8 +613,12 @@ std::shared_ptr buildModelExplicit(storm::settings::mo storm::parser::DirectEncodingValueType valueType{Default}; if constexpr (std::is_same_v) { valueType = Double; + } else if constexpr (std::is_same_v) { + valueType = DoubleInterval; } else if constexpr (std::is_same_v) { valueType = Rational; + } else if constexpr (std::is_same_v) { + valueType = RationalInterval; } else { static_assert(std::is_same_v, "Unexpected value type."); valueType = Parametric; @@ -1293,30 +1311,38 @@ inline std::vector> parseInjectedRef template void verifyWithAbstractionRefinementEngine(SymbolicInput const& input, ModelProcessingInformation const& mpi) { - STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); - storm::settings::modules::AbstractionSettings const& abstractionSettings = storm::settings::getModule(); - storm::gbar::api::AbstractionRefinementOptions options( - parseConstraints(input.model->getManager(), abstractionSettings.getConstraintString()), - parseInjectedRefinementPredicates(input.model->getManager(), abstractionSettings.getInjectedRefinementPredicates())); - - verifyProperties(input, [&input, &options, &mpi](std::shared_ptr const& formula, - std::shared_ptr const& states) { - STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Abstraction-refinement can only filter initial states."); - return storm::gbar::api::verifyWithAbstractionRefinementEngine(mpi.env, input.model.get(), - storm::api::createTask(formula, true), options); - }); + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Abstraction-refinement engine does not support interval value types."); + } else { + STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); + storm::settings::modules::AbstractionSettings const& abstractionSettings = storm::settings::getModule(); + storm::gbar::api::AbstractionRefinementOptions options( + parseConstraints(input.model->getManager(), abstractionSettings.getConstraintString()), + parseInjectedRefinementPredicates(input.model->getManager(), abstractionSettings.getInjectedRefinementPredicates())); + + verifyProperties(input, [&input, &options, &mpi](std::shared_ptr const& formula, + std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Abstraction-refinement can only filter initial states."); + return storm::gbar::api::verifyWithAbstractionRefinementEngine(mpi.env, input.model.get(), + storm::api::createTask(formula, true), options); + }); + } } template void verifyWithExplorationEngine(SymbolicInput const& input, ModelProcessingInformation const& mpi) { - STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); - STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, - "Exploration does not support other data-types than floating points."); - verifyProperties( - input, [&input, &mpi](std::shared_ptr const& formula, std::shared_ptr const& states) { - STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Exploration can only filter initial states."); - return storm::api::verifyWithExplorationEngine(mpi.env, input.model.get(), storm::api::createTask(formula, true)); - }); + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Exploration engine does not support interval value types."); + } else { + STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); + STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, + "Exploration does not support other data-types than floating points."); + verifyProperties( + input, [&input, &mpi](std::shared_ptr const& formula, std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Exploration can only filter initial states."); + return storm::api::verifyWithExplorationEngine(mpi.env, input.model.get(), storm::api::createTask(formula, true)); + }); + } } template From 45910bcb8fe800db2bc0a60bd59ce9d4059d500d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 10 Mar 2026 11:50:08 +0100 Subject: [PATCH 102/102] formatting --- resources/scripts/auto-format.sh | 4 +-- .../SparseMdpEndComponentInformation.cpp | 9 +++--- .../prctl/helper/SparseMdpPrctlHelper.cpp | 2 +- .../models/sparse/StandardRewardModel.cpp | 31 ++++++++++--------- .../settings/modules/GeneralSettings.cpp | 3 +- src/storm/transformer/SubsystemBuilder.cpp | 7 +++-- src/storm/utility/builder.cpp | 3 +- 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/resources/scripts/auto-format.sh b/resources/scripts/auto-format.sh index ba7cf542b8..3ac97c41af 100755 --- a/resources/scripts/auto-format.sh +++ b/resources/scripts/auto-format.sh @@ -16,7 +16,7 @@ do exit 1 fi done -if ! command -v clang-format-20 &> /dev/null +if ! command -v clang-format &> /dev/null then echo "Unable to find clang-format executable. Is it installed?" exit 1 @@ -49,4 +49,4 @@ auto_format_find_expression+=" -false ) ) -print" set -f # find files and invoke clang-format with in-place option -find $auto_format_find_expression | xargs clang-format-20 -i -style=file +find $auto_format_find_expression | xargs clang-format -i -style=file diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp index a90c6be484..9ef02c1c25 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp @@ -439,11 +439,10 @@ template void SparseMdpEndComponentInformation::setScheduler(st storm::storage::SparseMatrix const& backwardTransitions, std::vector const& fromResult); -template void SparseMdpEndComponentInformation::setScheduler(storm::storage::Scheduler& scheduler, - storm::storage::BitVector const& maybeStates, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, - std::vector const& fromResult); +template void SparseMdpEndComponentInformation::setScheduler( + storm::storage::Scheduler& scheduler, storm::storage::BitVector const& maybeStates, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, std::vector const& fromResult); // template class SparseMdpEndComponentInformation; diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 8f78376274..60a4d0a3b4 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -778,7 +778,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper>(*scheduler, resultForMaybeStates.getScheduler(), - qualitativeStateSets.maybeStates); + qualitativeStateSets.maybeStates); } } } diff --git a/src/storm/models/sparse/StandardRewardModel.cpp b/src/storm/models/sparse/StandardRewardModel.cpp index 92c451327f..6c8c8f03c6 100644 --- a/src/storm/models/sparse/StandardRewardModel.cpp +++ b/src/storm/models/sparse/StandardRewardModel.cpp @@ -663,13 +663,12 @@ template storm::storage::BitVector StandardRewardModel::getChoi template class StandardRewardModel; template std::ostream& operator<< (std::ostream& out, StandardRewardModel const& rewardModel); -template std::vector StandardRewardModel::getTotalRewardVector(uint_fast64_t numberOfRows, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::BitVector const& filter) const; +template std::vector StandardRewardModel::getTotalRewardVector( + uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& filter) const; template std::vector StandardRewardModel::getTotalRewardVector( storm::storage::SparseMatrix const& transitionMatrix) const; -template std::vector StandardRewardModel::getTotalRewardVector(storm::storage::SparseMatrix const& transitionMatrix, - std::vector const& weights) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& weights) const; template std::vector StandardRewardModel::getTotalRewardVector( uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& filter) const; template std::vector StandardRewardModel::getTotalRewardVector( @@ -678,25 +677,27 @@ template std::vector StandardRewardModel const& transitionMatrix, std::vector const& weights) const; template std::vector StandardRewardModel::getTotalActionRewardVector( storm::storage::SparseMatrix const& transitionMatrix, std::vector const& stateRewardWeights) const; -template storm::storage::BitVector StandardRewardModel::getStatesWithFilter(storm::storage::SparseMatrix const& transitionMatrix, - std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getStatesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; template storm::storage::BitVector StandardRewardModel::getStatesWithFilter( storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; -template storm::storage::BitVector StandardRewardModel::getChoicesWithFilter(storm::storage::SparseMatrix const& transitionMatrix, - std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getChoicesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; template storm::storage::BitVector StandardRewardModel::getChoicesWithFilter( storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; template void StandardRewardModel::setStateActionReward(uint_fast64_t choiceIndex, storm::RationalNumber const& newValue); template void StandardRewardModel::setStateActionReward(uint_fast64_t choiceIndex, storm::RationalInterval const& newValue); template void StandardRewardModel::setStateReward(uint_fast64_t state, storm::RationalNumber const& newValue); template void StandardRewardModel::setStateReward(uint_fast64_t state, storm::RationalInterval const& newValue); -template void StandardRewardModel::clearRewardAtState(uint_fast64_t state, storm::storage::SparseMatrix const& transitionMatrix); template void StandardRewardModel::clearRewardAtState(uint_fast64_t state, - storm::storage::SparseMatrix const& transitionMatrix); -template void StandardRewardModel::reduceToStateBasedRewards(storm::storage::SparseMatrix const& transitionMatrix, - bool reduceToStateRewards, std::vector const* weights); -template void StandardRewardModel::reduceToStateBasedRewards(storm::storage::SparseMatrix const& transitionMatrix, - bool reduceToStateRewards, std::vector const* weights); + storm::storage::SparseMatrix const& transitionMatrix); +template void StandardRewardModel::clearRewardAtState(uint_fast64_t state, + storm::storage::SparseMatrix const& transitionMatrix); +template void StandardRewardModel::reduceToStateBasedRewards( + storm::storage::SparseMatrix const& transitionMatrix, bool reduceToStateRewards, std::vector const* weights); +template void StandardRewardModel::reduceToStateBasedRewards( + storm::storage::SparseMatrix const& transitionMatrix, bool reduceToStateRewards, + std::vector const* weights); template storm::storage::BitVector StandardRewardModel::getStatesWithZeroReward( storm::storage::SparseMatrix const& transitionMatrix) const; template storm::storage::BitVector StandardRewardModel::getChoicesWithZeroReward( diff --git a/src/storm/settings/modules/GeneralSettings.cpp b/src/storm/settings/modules/GeneralSettings.cpp index 6ae58ce4ff..8b440ee61f 100644 --- a/src/storm/settings/modules/GeneralSettings.cpp +++ b/src/storm/settings/modules/GeneralSettings.cpp @@ -86,8 +86,7 @@ GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { .build()) .build()); this->addOption(storm::settings::OptionBuilder(moduleName, soundOptionName, false, "Sets whether to force sound model checking.").build()); - this->addOption( - storm::settings::OptionBuilder(moduleName, intervalOptionName, false, "Sets whether to enable interval model checking.").build()); + this->addOption(storm::settings::OptionBuilder(moduleName, intervalOptionName, false, "Sets whether to enable interval model checking.").build()); } bool GeneralSettings::isHelpSet() const { diff --git a/src/storm/transformer/SubsystemBuilder.cpp b/src/storm/transformer/SubsystemBuilder.cpp index e9a3a539b1..c19983994e 100644 --- a/src/storm/transformer/SubsystemBuilder.cpp +++ b/src/storm/transformer/SubsystemBuilder.cpp @@ -243,9 +243,10 @@ template SubsystemBuilderReturnType buildSubsystem(storm::model storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, SubsystemBuilderOptions options = SubsystemBuilderOptions()); template SubsystemBuilderReturnType buildSubsystem(storm::models::sparse::Model const& originalModel, - storm::storage::BitVector const& subsystemStates, - storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, - SubsystemBuilderOptions options = SubsystemBuilderOptions()); + storm::storage::BitVector const& subsystemStates, + storm::storage::BitVector const& subsystemActions, + bool keepUnreachableStates = true, + SubsystemBuilderOptions options = SubsystemBuilderOptions()); } // namespace transformer } // namespace storm diff --git a/src/storm/utility/builder.cpp b/src/storm/utility/builder.cpp index d1c9c65bb1..1a19e27316 100644 --- a/src/storm/utility/builder.cpp +++ b/src/storm/utility/builder.cpp @@ -43,7 +43,8 @@ template std::shared_ptr> buildModelFromCom template std::shared_ptr>> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents>&& components); -template std::shared_ptr>> buildModelFromComponents( +template std::shared_ptr>> +buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents>&& components); template std::shared_ptr> buildModelFromComponents(