diff --git a/src/storm-pars/modelchecker/region/RegionModelChecker.cpp b/src/storm-pars/modelchecker/region/RegionModelChecker.cpp index b3669e9b8..2b2e8a350 100644 --- a/src/storm-pars/modelchecker/region/RegionModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/RegionModelChecker.cpp @@ -11,13 +11,12 @@ #include "storm/models/sparse/Dtmc.h" #include "storm/models/sparse/Mdp.h" -#include "storm/exceptions/NotSupportedException.h" -#include "storm/exceptions/InvalidStateException.h" -#include "storm/exceptions/InvalidArgumentException.h" - #include "storm/settings/SettingsManager.h" #include "storm/settings/modules/CoreSettings.h" #include "storm/exceptions/NotImplementedException.h" +#include "storm/exceptions/NotSupportedException.h" +#include "storm/exceptions/InvalidStateException.h" +#include "storm/exceptions/InvalidArgumentException.h" namespace storm { @@ -152,6 +151,18 @@ namespace storm { auto regionCopyForResult = region; return std::make_unique>(std::move(result), std::move(regionCopyForResult)); } + + template + bool RegionModelChecker::isRegionSplitEstimateSupported() const { + return false; + } + + template + std::map::VariableType, double> RegionModelChecker::getRegionSplitEstimate() const { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Region split estimation is not supported by this region model checker."); + return std::map::VariableType, double>(); + } + #ifdef STORM_HAVE_CARL template class RegionModelChecker; diff --git a/src/storm-pars/modelchecker/region/RegionModelChecker.h b/src/storm-pars/modelchecker/region/RegionModelChecker.h index fc9997c3c..72f56bf73 100644 --- a/src/storm-pars/modelchecker/region/RegionModelChecker.h +++ b/src/storm-pars/modelchecker/region/RegionModelChecker.h @@ -22,12 +22,13 @@ namespace storm { public: typedef typename storm::storage::ParameterRegion::CoefficientType CoefficientType; + typedef typename storm::storage::ParameterRegion::VariableType VariableType; RegionModelChecker(); virtual ~RegionModelChecker() = default; virtual bool canHandle(std::shared_ptr parametricModel, CheckTask const& checkTask) const = 0; - virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) = 0; + virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates = false) = 0; /*! * Analyzes the given region. @@ -57,6 +58,17 @@ namespace storm { */ std::unique_ptr> performRegionRefinement(Environment const& env, storm::storage::ParameterRegion const& region, boost::optional const& coverageThreshold, boost::optional depthThreshold = boost::none, RegionResultHypothesis const& hypothesis = RegionResultHypothesis::Unknown); + /*! + * Returns true if region split estimation (a) was enabled when model and check task have been specified and (b) is supported by this region model checker. + */ + virtual bool isRegionSplitEstimateSupported() const; + + /*! + * Returns an estimate of the benefit of splitting the last checked region with respect to each parameter. This method should only be called if region split estimation is supported and enabled. + * If a parameter is assigned a high value, we should prefer splitting with respect to this parameter. + */ + virtual std::map getRegionSplitEstimate() const; + }; } //namespace modelchecker diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 7bce00c6a..9c009ccee 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -19,6 +19,7 @@ #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/NotSupportedException.h" #include "storm/exceptions/UnexpectedException.h" +#include "storm/exceptions/InvalidOperationException.h" #include "storm/exceptions/UncheckedRequirementException.h" @@ -31,7 +32,7 @@ namespace storm { } template - SparseDtmcParameterLiftingModelChecker::SparseDtmcParameterLiftingModelChecker(std::unique_ptr>&& solverFactory) : solverFactory(std::move(solverFactory)), solvingRequiresUpperRewardBounds(false) { + SparseDtmcParameterLiftingModelChecker::SparseDtmcParameterLiftingModelChecker(std::unique_ptr>&& solverFactory) : solverFactory(std::move(solverFactory)), solvingRequiresUpperRewardBounds(false), regionSplitEstimationsEnabled(false) { // Intentionally left empty } @@ -47,18 +48,20 @@ namespace storm { } template - void SparseDtmcParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) { + void SparseDtmcParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates) { auto dtmc = parametricModel->template as(); - specify(env, dtmc, checkTask, false); + specify(env, dtmc, checkTask, generateRegionSplitEstimates, false); } template - void SparseDtmcParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool skipModelSimplification) { - + void SparseDtmcParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates, bool skipModelSimplification) { + STORM_LOG_ASSERT(this->canHandle(parametricModel, checkTask), "specified model and formula can not be handled by this."); - + reset(); + regionSplitEstimationsEnabled = generateRegionSplitEstimates; + if (skipModelSimplification) { this->parametricModel = parametricModel; this->specifyFormula(env, checkTask); @@ -139,7 +142,7 @@ namespace storm { // Create the vector of one-step probabilities to go to target states. std::vector b = this->parametricModel->getTransitionMatrix().getConstrainedRowSumVector(storm::storage::BitVector(this->parametricModel->getTransitionMatrix().getRowCount(), true), psiStates); - parameterLifter = std::make_unique>(this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates); + parameterLifter = std::make_unique>(this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates, regionSplitEstimationsEnabled); } // We know some bounds for the results so set them @@ -179,7 +182,7 @@ namespace storm { std::vector b = rewardModel.getTotalRewardVector(this->parametricModel->getTransitionMatrix()); - parameterLifter = std::make_unique>(this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates); + parameterLifter = std::make_unique>(this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates, regionSplitEstimationsEnabled); } // We only know a lower bound for the result @@ -297,6 +300,9 @@ namespace storm { } else { maxSchedChoices = solver->getSchedulerChoices(); } + if (isRegionSplitEstimateSupported()) { + computeRegionSplitEstimates(x, solver->getSchedulerChoices(), region, dirForParameters); + } } // Get the result for the complete model (including maybestates) @@ -309,6 +315,68 @@ namespace storm { return std::make_unique>(std::move(result)); } + template + void SparseDtmcParameterLiftingModelChecker::computeRegionSplitEstimates(std::vector const& quantitativeResult, std::vector const& schedulerChoices, storm::storage::ParameterRegion const& region, storm::solver::OptimizationDirection const& dirForParameters) { + std::map::VariableType, double> deltaLower, deltaUpper; + for (auto const& p : region.getVariables()) { + deltaLower.insert(std::make_pair(p, 0.0)); + deltaUpper.insert(std::make_pair(p, 0.0)); + } + auto const& choiceValuations = parameterLifter->getRowLabels(); + auto const& matrix = parameterLifter->getMatrix(); + auto const& vector = parameterLifter->getVector(); + + std::vector stateResults; + for (uint64_t state = 0; state < schedulerChoices.size(); ++state) { + uint64_t rowOffset = matrix.getRowGroupIndices()[state]; + uint64_t optimalChoice = schedulerChoices[state]; + auto const& optimalChoiceVal = choiceValuations[rowOffset + optimalChoice]; + assert(optimalChoiceVal.getUnspecifiedParameters().empty()); + stateResults.clear(); + for (uint64_t row = rowOffset; row < matrix.getRowGroupIndices()[state + 1]; ++row) { + stateResults.push_back(matrix.multiplyRowWithVector(row, quantitativeResult) + vector[row]); + } + bool checkUpperParameters = false; + do { + auto const& consideredParameters = checkUpperParameters ? optimalChoiceVal.getUpperParameters() : optimalChoiceVal.getLowerParameters(); + for (auto const& p : consideredParameters) { + // Find the 'best' choice that assigns the parameter to the other bound + ConstantType bestValue; + bool foundBestValue = false; + for (uint64_t choice = 0; choice < stateResults.size(); ++choice) { + if (choice != optimalChoice) { + auto const& otherBoundParsOfChoice = checkUpperParameters ? choiceValuations[rowOffset + choice].getLowerParameters() : choiceValuations[rowOffset + choice].getUpperParameters(); + if (otherBoundParsOfChoice.find(p) != otherBoundParsOfChoice.end()) { + ConstantType const& choiceValue = stateResults[choice]; + if (!foundBestValue || (storm::solver::minimize(dirForParameters) ? choiceValue < bestValue : choiceValue > bestValue)) { + foundBestValue = true; + bestValue = choiceValue; + } + } + } + } + if (checkUpperParameters) { + deltaLower[p] += storm::utility::convertNumber(bestValue); + } else { + deltaUpper[p] += storm::utility::convertNumber(bestValue); + } + + } + checkUpperParameters = !checkUpperParameters; + } while (checkUpperParameters); + } + + regionSplitEstimates.clear(); + for (auto const& p : region.getVariables()) { + if (deltaLower[p] > deltaUpper[p]) { + regionSplitEstimates.insert(std::make_pair(p, deltaUpper[p])); + } else { + regionSplitEstimates.insert(std::make_pair(p, deltaLower[p])); + } + } + + } + template void SparseDtmcParameterLiftingModelChecker::reset() { maybeStates.resize(0); @@ -321,6 +389,7 @@ namespace storm { x.clear(); lowerResultBound = boost::none; upperResultBound = boost::none; + regionSplitEstimationsEnabled = false; } template @@ -355,6 +424,18 @@ namespace storm { return result; } + template + bool SparseDtmcParameterLiftingModelChecker::isRegionSplitEstimateSupported() const { + return regionSplitEstimationsEnabled && !stepBound; + } + + template + std::map::VariableType, double> SparseDtmcParameterLiftingModelChecker::getRegionSplitEstimate() const { + STORM_LOG_THROW(isRegionSplitEstimateSupported(), storm::exceptions::InvalidOperationException, "Region split estimation requested but are not enabled (or supported)."); + return regionSplitEstimates; + } + + template class SparseDtmcParameterLiftingModelChecker, double>; template class SparseDtmcParameterLiftingModelChecker, storm::RationalNumber>; diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h index 18bb302b9..88231e76c 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h @@ -23,12 +23,15 @@ namespace storm { virtual ~SparseDtmcParameterLiftingModelChecker() = default; virtual bool canHandle(std::shared_ptr parametricModel, CheckTask const& checkTask) const override; - virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) override; - void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool skipModelSimplification); + virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates = false) override; + void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates, bool skipModelSimplification); boost::optional> getCurrentMinScheduler(); boost::optional> getCurrentMaxScheduler(); + virtual bool isRegionSplitEstimateSupported() const override; + virtual std::map::VariableType, double> getRegionSplitEstimate() const override; + protected: virtual void specifyBoundedUntilFormula(Environment const& env, CheckTask const& checkTask) override; @@ -39,7 +42,9 @@ namespace storm { virtual storm::modelchecker::SparseInstantiationModelChecker& getInstantiationChecker() override; virtual std::unique_ptr computeQuantitativeValues(Environment const& env, storm::storage::ParameterRegion const& region, storm::solver::OptimizationDirection const& dirForParameters) override; - + + void computeRegionSplitEstimates(std::vector const& quantitativeResult, std::vector const& schedulerChoices, storm::storage::ParameterRegion const& region, storm::solver::OptimizationDirection const& dirForParameters); + virtual void reset() override; private: @@ -59,6 +64,9 @@ namespace storm { boost::optional> minSchedChoices, maxSchedChoices; std::vector x; boost::optional lowerResultBound, upperResultBound; + + bool regionSplitEstimationsEnabled; + std::map::VariableType, double> regionSplitEstimates; }; } } diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index 04a5c41e1..55a1b65a7 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -45,13 +45,13 @@ namespace storm { } template - void SparseMdpParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) { + void SparseMdpParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates) { auto mdp = parametricModel->template as(); - specify(env, mdp, checkTask, false); + specify(env, mdp, checkTask, generateRegionSplitEstimates, false); } template - void SparseMdpParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool skipModelSimplification) { + void SparseMdpParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates, bool skipModelSimplification) { STORM_LOG_ASSERT(this->canHandle(parametricModel, checkTask), "specified model and formula can not be handled by this."); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.h b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.h index 09a3e44cb..cffab74ed 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.h +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.h @@ -25,8 +25,8 @@ namespace storm { virtual ~SparseMdpParameterLiftingModelChecker() = default; virtual bool canHandle(std::shared_ptr parametricModel, CheckTask const& checkTask) const override; - virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) override; - void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool skipModelSimplification); + virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates = false) override; + void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates, bool skipModelSimplification); boost::optional> getCurrentMinScheduler(); boost::optional> getCurrentMaxScheduler(); diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.cpp index e95cf2d61..e84f6c9d0 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.cpp @@ -15,7 +15,7 @@ namespace storm { } template - void ValidatingSparseDtmcParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) { + void ValidatingSparseDtmcParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates) { STORM_LOG_ASSERT(this->canHandle(parametricModel, checkTask), "specified model and formula can not be handled by this."); auto dtmc = parametricModel->template as(); @@ -27,8 +27,8 @@ namespace storm { auto simplifiedTask = checkTask.substituteFormula(*simplifier.getSimplifiedFormula()); - impreciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, true); - preciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, true); + impreciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, false, true); + preciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, false, true); } template diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.h b/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.h index f441353fb..5aed6b5d3 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.h +++ b/src/storm-pars/modelchecker/region/ValidatingSparseDtmcParameterLiftingModelChecker.h @@ -12,7 +12,7 @@ namespace storm { ValidatingSparseDtmcParameterLiftingModelChecker(); virtual ~ValidatingSparseDtmcParameterLiftingModelChecker() = default; - virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) override; + virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates = false) override; protected: virtual SparseParameterLiftingModelChecker& getImpreciseChecker() override; diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.cpp index 7cdb1c7b0..a3c01b4bd 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.cpp @@ -16,7 +16,7 @@ namespace storm { template - void ValidatingSparseMdpParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) { + void ValidatingSparseMdpParameterLiftingModelChecker::specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates) { STORM_LOG_ASSERT(this->canHandle(parametricModel, checkTask), "specified model and formula can not be handled by this."); auto mdp = parametricModel->template as(); @@ -28,8 +28,8 @@ namespace storm { auto simplifiedTask = checkTask.substituteFormula(*simplifier.getSimplifiedFormula()); - impreciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, true); - preciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, true); + impreciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, false, true); + preciseChecker.specify(env, simplifier.getSimplifiedModel(), simplifiedTask, false, true); } template diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.h b/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.h index fdb304747..d6ef0ba74 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.h +++ b/src/storm-pars/modelchecker/region/ValidatingSparseMdpParameterLiftingModelChecker.h @@ -12,7 +12,7 @@ namespace storm { ValidatingSparseMdpParameterLiftingModelChecker(); virtual ~ValidatingSparseMdpParameterLiftingModelChecker() = default; - virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask) override; + virtual void specify(Environment const& env, std::shared_ptr parametricModel, CheckTask const& checkTask, bool generateRegionSplitEstimates = false) override; protected: virtual SparseParameterLiftingModelChecker& getImpreciseChecker() override; diff --git a/src/storm-pars/transformer/ParameterLifter.cpp b/src/storm-pars/transformer/ParameterLifter.cpp index 551529c4c..9eba6e8f2 100644 --- a/src/storm-pars/transformer/ParameterLifter.cpp +++ b/src/storm-pars/transformer/ParameterLifter.cpp @@ -12,8 +12,9 @@ namespace storm { namespace transformer { template - ParameterLifter::ParameterLifter(storm::storage::SparseMatrix const& pMatrix, std::vector const& pVector, storm::storage::BitVector const& selectedRows, storm::storage::BitVector const& selectedColumns) { + ParameterLifter::ParameterLifter(storm::storage::SparseMatrix const& pMatrix, std::vector const& pVector, storm::storage::BitVector const& selectedRows, storm::storage::BitVector const& selectedColumns, bool generateRowLabels) { + // get a mapping from old column indices to new ones std::vector oldToNewColumnIndexMapping(selectedColumns.size(), selectedColumns.size()); uint_fast64_t newIndex = 0; @@ -45,10 +46,16 @@ namespace storm { ++pMatrixEntryCount; } } + ParametricType const& pVectorEntry = pVector[rowIndex]; std::set vectorEntryVariables; if (!storm::utility::isConstant(pVectorEntry)) { storm::utility::parametric::gatherOccurringVariables(pVectorEntry, vectorEntryVariables); + if (generateRowLabels) { + // If row labels are to be generated, we do not allow unspecified valuations. + // Therefore, we also 'lift' parameters that only occurr on a vector. + occurringVariables.insert(vectorEntryVariables.begin(), vectorEntryVariables.end()); + } nonConstVectorEntries.set(pVectorEntryCount, true); } ++pVectorEntryCount; @@ -57,6 +64,10 @@ namespace storm { auto rowValuations = getVerticesOfAbstractRegion(occurringVariables); for (auto const& val : rowValuations) { + if (generateRowLabels) { + rowLabels.push_back(val); + } + // Insert matrix entries for each valuation. For non-constant entries, a dummy value is inserted and the function and the valuation are collected. // The placeholder for the collected function/valuation are stored in the matrixAssignment. The matrixAssignment is completed after the matrix is finished for (auto const& entry: pMatrix.getRow(rowIndex)) { @@ -78,7 +89,8 @@ namespace storm { vector.push_back(storm::utility::one()); AbstractValuation vectorVal(val); for(auto const& vectorVar : vectorEntryVariables) { - if(occurringVariables.find(vectorVar) == occurringVariables.end()) { + if (occurringVariables.find(vectorVar) == occurringVariables.end()) { + assert(!generateRowLabels); vectorVal.addParameterUnspecified(vectorVar); } } @@ -148,6 +160,11 @@ namespace storm { std::vector const& ParameterLifter::getVector() const { return vector; } + + template + std::vector::AbstractValuation> const& ParameterLifter::getRowLabels() const { + return rowLabels; + } template std::vector::AbstractValuation> ParameterLifter::getVerticesOfAbstractRegion(std::set const& variables) const { @@ -223,6 +240,21 @@ namespace storm { return result; } + template + std::set::VariableType> const& ParameterLifter::AbstractValuation::getLowerParameters() const { + return lowerPars; + } + + template + std::set::VariableType> const& ParameterLifter::AbstractValuation::getUpperParameters() const { + return upperPars; + } + + template + std::set::VariableType> const& ParameterLifter::AbstractValuation::getUnspecifiedParameters() const { + return unspecifiedPars; + } + template std::vector> ParameterLifter::AbstractValuation::getConcreteValuations(storm::storage::ParameterRegion const& region) const { auto result = region.getVerticesOfRegion(unspecifiedPars); diff --git a/src/storm-pars/transformer/ParameterLifter.h b/src/storm-pars/transformer/ParameterLifter.h index ab16e5a88..c7837fa5c 100644 --- a/src/storm-pars/transformer/ParameterLifter.h +++ b/src/storm-pars/transformer/ParameterLifter.h @@ -39,7 +39,7 @@ namespace storm { * @param selectedRows a Bitvector that specifies which rows of the matrix and the vector are considered. * @param selectedColumns a Bitvector that specifies which columns of the matrix are considered. */ - ParameterLifter(storm::storage::SparseMatrix const& pMatrix, std::vector const& pVector, storm::storage::BitVector const& selectedRows, storm::storage::BitVector const& selectedColumns); + ParameterLifter(storm::storage::SparseMatrix const& pMatrix, std::vector const& pVector, storm::storage::BitVector const& selectedRows, storm::storage::BitVector const& selectedColumns, bool generateRowLabels = false); void specifyRegion(storm::storage::ParameterRegion const& region, storm::solver::OptimizationDirection const& dirForParameters); @@ -49,13 +49,6 @@ namespace storm { // Returns the resulting vector. Should only be called AFTER specifying a region std::vector const& getVector() const; - - private: - /* - * We minimize the number of function evaluations by only calling evaluate() once for each unique pair of function and valuation. - * The result of each evaluation is then written to all positions in the matrix (and the vector) where the corresponding (function,valuation) occurred. - */ - /* * During initialization, the actual regions are not known. Hence, we consider abstract valuations, * where it is only known whether a parameter will be set to either the lower/upper bound of the region or whether this is unspecified @@ -72,6 +65,9 @@ namespace storm { std::size_t getHashValue() const; AbstractValuation getSubValuation(std::set const& pars) const; + std::set const& getLowerParameters() const; + std::set const& getUpperParameters() const; + std::set const& getUnspecifiedParameters() const; /*! * Returns the concrete valuation(s) (w.r.t. the provided region) represented by this abstract valuation. @@ -83,6 +79,17 @@ namespace storm { std::set lowerPars, upperPars, unspecifiedPars; }; + // Returns for each row the abstract valuation for this row + // Note: the returned vector might be empty if row label generaion was disabled initially + std::vector const& getRowLabels() const; + + + private: + /* + * We minimize the number of function evaluations by only calling evaluate() once for each unique pair of function and valuation. + * The result of each evaluation is then written to all positions in the matrix (and the vector) where the corresponding (function,valuation) occurred. + */ + /*! * Collects all occurring pairs of functions and (abstract) valuations. * We also store a placeholder for the result of each pair. The result is computed and written into the placeholder whenever a region and optimization direction is specified. @@ -121,7 +128,8 @@ namespace storm { // Returns the 2^(variables.size()) vertices of the region std::vector getVerticesOfAbstractRegion(std::set const& variables) const; - + std::vector rowLabels; + storm::storage::SparseMatrix matrix; //The resulting matrix; std::vector::iterator, ConstantType&>> matrixAssignment; // Connection of matrix entries with placeholders