Browse Source

performance improvement in DS-MPI; some cleanups

tempestpy_adaptions
dehnert 7 years ago
parent
commit
b4bfd0c39f
  1. 5
      src/storm-cli-utilities/model-handling.h
  2. 37
      src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp
  3. 182
      src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp
  4. 26
      src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp
  5. 6
      src/storm/solver/LinearEquationSolverRequirements.cpp
  6. 1
      src/storm/solver/LinearEquationSolverRequirements.h
  7. 6
      src/storm/solver/MinMaxLinearEquationSolverRequirements.cpp
  8. 1
      src/storm/solver/MinMaxLinearEquationSolverRequirements.h
  9. 7
      src/storm/solver/NativeLinearEquationSolver.cpp
  10. 81
      src/storm/storage/ConsecutiveUint64DynamicPriorityQueue.h
  11. 99
      src/storm/storage/VectorDynamicPriorityQueue.h

5
src/storm-cli-utilities/model-handling.h

@ -629,6 +629,8 @@ namespace storm {
} else {
std::shared_ptr<storm::models::ModelBase> model = buildPreprocessExportModelWithValueTypeAndDdlib<DdType, ValueType>(input, engine);
STORM_LOG_THROW(model->isSparseModel() || !storm::settings::getModule<storm::settings::modules::GeneralSettings>().isSoundSet(), storm::exceptions::NotSupportedException, "Forcing soundness is currently only supported for sparse models.");
if (model) {
if (coreSettings.isCounterexampleSet()) {
auto ioSettings = storm::settings::getModule<storm::settings::modules::IOSettings>();
@ -644,9 +646,6 @@ namespace storm {
template <typename ValueType>
void processInputWithValueType(SymbolicInput const& input) {
auto coreSettings = storm::settings::getModule<storm::settings::modules::CoreSettings>();
auto generalSettings = storm::settings::getModule<storm::settings::modules::GeneralSettings>();
STORM_LOG_THROW(!generalSettings.isSoundSet() || coreSettings.getEngine() == storm::settings::modules::CoreSettings::Engine::Sparse, storm::exceptions::NotSupportedException, "Forcing soundness is not supported for engines other than the sparse engine.");
if (coreSettings.getDdLibraryType() == storm::dd::DdType::CUDD) {
processInputWithValueTypeAndDdlib<storm::dd::DdType::CUDD, ValueType>(input);

37
src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp

@ -8,12 +8,16 @@
#include "storm/storage/StronglyConnectedComponentDecomposition.h"
#include "storm/storage/DynamicPriorityQueue.h"
#include "storm/storage/ConsecutiveUint64DynamicPriorityQueue.h"
#include "storm/solver/LinearEquationSolver.h"
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
#include "storm/modelchecker/hints/ExplicitModelCheckerHint.h"
#include "storm/utility/macros.h"
#include "storm/utility/ConstantsComparator.h"
#include "storm/exceptions/InvalidStateException.h"
#include "storm/exceptions/InvalidPropertyException.h"
#include "storm/exceptions/IllegalArgumentException.h"
@ -235,6 +239,17 @@ namespace storm {
result[state] = w[state] + (one - p[state]) * lambda;
}
#ifndef NDEBUG
ValueType max = storm::utility::zero<ValueType>();
uint64_t nonZeroCount = 0;
for (auto const& e : result) {
if (!storm::utility::isZero(e)) {
++nonZeroCount;
max = std::max(max, e);
}
}
STORM_LOG_TRACE("DS-MPI computed " << nonZeroCount << " non-zero upper bounds and a maximal bound of " << max << ".");
#endif
return result;
}
@ -269,7 +284,7 @@ namespace storm {
for (auto const& e : transitionMatrix.getRow(state)) {
sum += e.getValue() * w[e.getColumn()];
}
STORM_LOG_WARN_COND(w[state] >= sum, "Expected condition (II) to hold in state " << state << ", but " << w[state] << " < " << sum << ".");
STORM_LOG_WARN_COND(w[state] >= sum || storm::utility::ConstantsComparator<ValueType>().isEqual(w[state], sum), "Expected condition (II) to hold in state " << state << ", but " << w[state] << " < " << sum << ".");
#endif
}
}
@ -299,18 +314,9 @@ namespace storm {
void sweep() {
// Create a priority queue that allows for easy retrieval of the currently best state.
storm::storage::DynamicPriorityQueue<storm::storage::sparse::state_type, std::vector<storm::storage::sparse::state_type>, PriorityLess> queue(PriorityLess(*this));
storm::storage::ConsecutiveUint64DynamicPriorityQueue<PriorityLess> queue(transitionMatrix.getRowCount(), PriorityLess(*this));
storm::storage::BitVector visited(p.size());
storm::storage::BitVector inQueue(p.size());
for (storm::storage::sparse::state_type state = 0; state < targetProbabilities.size(); ++state) {
if (!storm::utility::isZero(targetProbabilities[state])) {
queue.push(state);
inQueue.set(state);
}
}
queue.fix();
while (!queue.empty()) {
// Get first entry in queue.
@ -332,13 +338,8 @@ namespace storm {
rewards[e.getColumn()] += e.getValue() * w[currentState];
targetProbabilities[e.getColumn()] += e.getValue() * p[currentState];
// Either insert element or simply fix the queue.
if (!inQueue.get(e.getColumn())) {
queue.push(e.getColumn());
inQueue.set(e.getColumn());
} else {
queue.fix();
}
// Increase priority of element.
queue.increase(e.getColumn());
}
}
}

182
src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp

@ -203,7 +203,10 @@ namespace storm {
// Check for requirements of the solver.
storm::solver::MinMaxLinearEquationSolverRequirements requirements = minMaxLinearEquationSolverFactory.getRequirements(type, dir);
if (!(hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint<ValueType>().getNoEndComponentsInMaybeStates()) && !requirements.empty()) {
if (!requirements.empty()) {
if (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint<ValueType>().getNoEndComponentsInMaybeStates()) {
requirements.clearNoEndComponents();
}
if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) {
STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it.");
result.schedulerHint = computeValidSchedulerHint(type, transitionMatrix, backwardTransitions, maybeStates, phiStates, targetStates);
@ -286,52 +289,106 @@ namespace storm {
return result;
}
struct QualitativeStateSetsUntilProbabilities {
storm::storage::BitVector maybeStates;
storm::storage::BitVector statesWithProbability0;
storm::storage::BitVector statesWithProbability1;
};
template<typename ValueType>
MDPSparseModelCheckingHelperReturnType<ValueType> SparseMdpPrctlHelper<ValueType>::computeUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory<ValueType> const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) {
STORM_LOG_THROW(!(qualitative && produceScheduler), storm::exceptions::InvalidSettingsException, "Cannot produce scheduler when performing qualitative model checking only.");
std::vector<ValueType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
// We need to identify the maybe states (states which have a probability for satisfying the until formula
// that is strictly between 0 and 1) and the states that satisfy the formula with probablity 1 and 0, respectively.
storm::storage::BitVector maybeStates, statesWithProbability1, statesWithProbability0;
QualitativeStateSetsUntilProbabilities getQualitativeStateSetsUntilProbabilitiesFromHint(ModelCheckerHint const& hint) {
QualitativeStateSetsUntilProbabilities result;
result.maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
// Treat the states with probability zero/one.
std::vector<ValueType> const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getResultHint();
result.statesWithProbability1 = storm::storage::BitVector(result.maybeStates.size());
result.statesWithProbability0 = storm::storage::BitVector(result.maybeStates.size());
storm::storage::BitVector nonMaybeStates = ~result.maybeStates;
for (auto const& state : nonMaybeStates) {
if (storm::utility::isOne(resultsForNonMaybeStates[state])) {
result.statesWithProbability1.set(state, true);
} else {
STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException, "Expected that the result hint specifies probabilities in {0,1} for non-maybe states");
result.statesWithProbability0.set(state, true);
}
}
return result;
}
template<typename ValueType>
QualitativeStateSetsUntilProbabilities computeQualitativeStateSetsUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
QualitativeStateSetsUntilProbabilities result;
// Get all states that have probability 0 and 1 of satisfying the until-formula.
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01;
if (goal.minimize()) {
statesWithProbability01 = storm::utility::graph::performProb01Min(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
} else {
statesWithProbability01 = storm::utility::graph::performProb01Max(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
}
result.statesWithProbability0 = std::move(statesWithProbability01.first);
result.statesWithProbability1 = std::move(statesWithProbability01.second);
result.maybeStates = ~(result.statesWithProbability0 | result.statesWithProbability1);
STORM_LOG_INFO("Found " << result.statesWithProbability0.getNumberOfSetBits() << " 'no' states.");
STORM_LOG_INFO("Found " << result.statesWithProbability1.getNumberOfSetBits() << " 'yes' states.");
STORM_LOG_INFO("Found " << result.maybeStates.getNumberOfSetBits() << " 'maybe' states.");
return result;
}
template<typename ValueType>
QualitativeStateSetsUntilProbabilities getQualitativeStateSetsUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, ModelCheckerHint const& hint) {
if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
// Treat the states with probability one
std::vector<ValueType> const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getResultHint();
statesWithProbability1 = storm::storage::BitVector(maybeStates.size(), false);
statesWithProbability0 = storm::storage::BitVector(maybeStates.size(), false);
storm::storage::BitVector nonMaybeStates = ~maybeStates;
for (auto const& state : nonMaybeStates) {
if (storm::utility::isOne(resultsForNonMaybeStates[state])) {
statesWithProbability1.set(state, true);
result[state] = storm::utility::one<ValueType>();
} else {
STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException, "Expected that the result hint specifies probabilities in {0,1} for non-maybe states");
statesWithProbability0.set(state, true);
}
return getQualitativeStateSetsUntilProbabilitiesFromHint<ValueType>(hint);
} else {
return computeQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates);
}
}
template<typename ValueType>
void extractSchedulerChoices(storm::storage::Scheduler<ValueType>& scheduler, std::vector<uint_fast64_t> const& subChoices, storm::storage::BitVector const& maybeStates) {
auto subChoiceIt = subChoices.begin();
for (auto maybeState : maybeStates) {
scheduler.setChoice(*subChoiceIt, maybeState);
++subChoiceIt;
}
assert(subChoiceIt == subChoices.end());
}
template<typename ValueType>
void extendScheduler(storm::storage::Scheduler<ValueType>& scheduler, storm::solver::SolveGoal const& goal, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
// Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for
// the states with probability 1 or 0 (depending on whether we maximize or minimize).
// We also need to define some arbitrary choice for the remaining states to obtain a fully defined scheduler.
if (goal.minimize()) {
storm::utility::graph::computeSchedulerProb0E(qualitativeStateSets.statesWithProbability0, transitionMatrix, scheduler);
for (auto const& prob1State : qualitativeStateSets.statesWithProbability1) {
scheduler.setChoice(0, prob1State);
}
} else {
// Get all states that have probability 0 and 1 of satisfying the until-formula.
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01;
if (goal.minimize()) {
statesWithProbability01 = storm::utility::graph::performProb01Min(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
} else {
statesWithProbability01 = storm::utility::graph::performProb01Max(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
storm::utility::graph::computeSchedulerProb1E(qualitativeStateSets.statesWithProbability1, transitionMatrix, backwardTransitions, phiStates, psiStates, scheduler);
for (auto const& prob0State : qualitativeStateSets.statesWithProbability0) {
scheduler.setChoice(0, prob0State);
}
statesWithProbability0 = std::move(statesWithProbability01.first);
statesWithProbability1 = std::move(statesWithProbability01.second);
maybeStates = ~(statesWithProbability0 | statesWithProbability1);
STORM_LOG_INFO("Found " << statesWithProbability0.getNumberOfSetBits() << " 'no' states.");
STORM_LOG_INFO("Found " << statesWithProbability1.getNumberOfSetBits() << " 'yes' states.");
STORM_LOG_INFO("Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states.");
// Set values of resulting vector that are known exactly.
storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability0, storm::utility::zero<ValueType>());
storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability1, storm::utility::one<ValueType>());
}
}
template<typename ValueType>
MDPSparseModelCheckingHelperReturnType<ValueType> SparseMdpPrctlHelper<ValueType>::computeUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory<ValueType> const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) {
STORM_LOG_THROW(!qualitative || !produceScheduler, storm::exceptions::InvalidSettingsException, "Cannot produce scheduler when performing qualitative model checking only.");
// Prepare resulting vector.
std::vector<ValueType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
// We need to identify the maybe states (states which have a probability for satisfying the until formula
// that is strictly between 0 and 1) and the states that satisfy the formula with probablity 1 and 0, respectively.
QualitativeStateSetsUntilProbabilities qualitativeStateSets = getQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates, hint);
// Set values of resulting vector that are known exactly.
storm::utility::vector::setVectorValues<ValueType>(result, qualitativeStateSets.statesWithProbability1, storm::utility::one<ValueType>());
// If requested, we will produce a scheduler.
std::unique_ptr<storm::storage::Scheduler<ValueType>> scheduler;
@ -342,60 +399,43 @@ namespace storm {
// Check whether we need to compute exact probabilities for some states.
if (qualitative) {
// Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1.
storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, storm::utility::convertNumber<ValueType>(0.5));
storm::utility::vector::setVectorValues<ValueType>(result, qualitativeStateSets.maybeStates, storm::utility::convertNumber<ValueType>(0.5));
} else {
if (!maybeStates.empty()) {
// In this case we have have to compute the probabilities.
if (!qualitativeStateSets.maybeStates.empty()) {
// In this case we have have to compute the remaining probabilities.
// First, we can eliminate the rows and columns from the original transition probability matrix for states
// whose probabilities are already known.
storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false);
storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false);
// Prepare the right-hand side of the equation system. For entry i this corresponds to
// the accumulated probability of going from state i to some 'yes' state.
std::vector<ValueType> b = transitionMatrix.getConstrainedRowGroupSumVector(maybeStates, statesWithProbability1);
// the accumulated probability of going from state i to some state that has probability 1.
std::vector<ValueType> b = transitionMatrix.getConstrainedRowGroupSumVector(qualitativeStateSets.maybeStates, qualitativeStateSets.statesWithProbability1);
// Obtain proper hint information either from the provided hint or from requirements of the solver.
SparseMdpHintType<ValueType> hintInformation = computeHints(storm::solver::EquationSystemType::UntilProbabilities, hint, goal.direction(), transitionMatrix, backwardTransitions, maybeStates, phiStates, statesWithProbability1, minMaxLinearEquationSolverFactory);
SparseMdpHintType<ValueType> hintInformation = computeHints(storm::solver::EquationSystemType::UntilProbabilities, hint, goal.direction(), transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates, phiStates, qualitativeStateSets.statesWithProbability1, minMaxLinearEquationSolverFactory);
// Now compute the results for the maybe states.
MaybeStateResult<ValueType> resultForMaybeStates = computeValuesForMaybeStates(goal, submatrix, b, produceScheduler, minMaxLinearEquationSolverFactory, hintInformation);
// Set values of resulting vector according to result.
storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, resultForMaybeStates.getValues());
storm::utility::vector::setVectorValues<ValueType>(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
if (produceScheduler) {
std::vector<uint_fast64_t> const& subChoices = resultForMaybeStates.getScheduler();
auto subChoiceIt = subChoices.begin();
for (auto maybeState : maybeStates) {
scheduler->setChoice(*subChoiceIt, maybeState);
++subChoiceIt;
}
assert(subChoiceIt == subChoices.end());
extractSchedulerChoices(*scheduler, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates);
}
}
}
// Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for
// the states with probability 1 or 0 (depending on whether we maximize or minimize).
// We also need to define some arbitrary choice for the remaining states to obtain a fully defined scheduler.
// Extend scheduler with choices for the states in the qualitative state sets.
if (produceScheduler) {
if (goal.minimize()) {
storm::utility::graph::computeSchedulerProb0E(statesWithProbability0, transitionMatrix, *scheduler);
for (auto const& prob1State : statesWithProbability1) {
scheduler->setChoice(0, prob1State);
}
} else {
storm::utility::graph::computeSchedulerProb1E(statesWithProbability1, transitionMatrix, backwardTransitions, phiStates, psiStates, *scheduler);
for (auto const& prob0State : statesWithProbability0) {
scheduler->setChoice(0, prob0State);
}
}
extendScheduler(*scheduler, goal, qualitativeStateSets, transitionMatrix, backwardTransitions, phiStates, psiStates);
}
// Sanity check for created scheduler.
STORM_LOG_ASSERT((!produceScheduler && !scheduler) || (!scheduler->isPartialScheduler() && scheduler->isDeterministicScheduler() && scheduler->isMemorylessScheduler()), "Unexpected format of obtained scheduler.");
// Return result.
return MDPSparseModelCheckingHelperReturnType<ValueType>(std::move(result), std::move(scheduler));
}

26
src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp

@ -251,15 +251,23 @@ namespace storm {
// Start by copying the requirements of the linear equation solver.
MinMaxLinearEquationSolverRequirements requirements(this->linearEquationSolverFactory->getRequirements());
// If we will use sound value iteration, we require no ECs and an upper bound.
if (this->getSettings().getSolutionMethod() == IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration && this->getSettings().getForceSoundness()) {
if (!direction || direction.get() == OptimizationDirection::Maximize) {
requirements.requireNoEndComponents();
// Guide requirements by whether or not we force soundness.
if (this->getSettings().getForceSoundness()) {
// Only add requirements for value iteration here as the policy iteration requirements are indifferent
if (this->getSettings().getSolutionMethod() == IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration) {
if (equationSystemType == EquationSystemType::UntilProbabilities) {
if (!direction || direction.get() == OptimizationDirection::Maximize) {
requirements.requireNoEndComponents();
}
} else if (equationSystemType == EquationSystemType::ReachabilityRewards) {
if (!direction || direction.get() == OptimizationDirection::Minimize) {
requirements.requireNoEndComponents();
}
}
}
requirements.requireUpperBounds();
}
// Then add our requirements on top of that.
// 'Regular' requirements (even for non-sound solving techniques).
if (equationSystemType == EquationSystemType::UntilProbabilities) {
if (this->getSettings().getSolutionMethod() == IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::PolicyIteration) {
if (!direction || direction.get() == OptimizationDirection::Maximize) {
@ -271,11 +279,7 @@ namespace storm {
requirements.requireValidInitialScheduler();
}
}
if (this->getSettings().getSolutionMethod() == IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration && this->getSettings().getForceSoundness()) {
requirements.requireUpperBounds();
}
return requirements;
}

6
src/storm/solver/LinearEquationSolverRequirements.cpp

@ -17,6 +17,12 @@ namespace storm {
return *this;
}
LinearEquationSolverRequirements& LinearEquationSolverRequirements::requireBounds() {
requireLowerBounds();
requireUpperBounds();
return *this;
}
bool LinearEquationSolverRequirements::requiresLowerBounds() const {
return lowerBounds;
}

1
src/storm/solver/LinearEquationSolverRequirements.h

@ -16,6 +16,7 @@ namespace storm {
LinearEquationSolverRequirements& requireLowerBounds();
LinearEquationSolverRequirements& requireUpperBounds();
LinearEquationSolverRequirements& requireBounds();
bool requiresLowerBounds() const;
bool requiresUpperBounds() const;

6
src/storm/solver/MinMaxLinearEquationSolverRequirements.cpp

@ -27,6 +27,12 @@ namespace storm {
return *this;
}
MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::requireBounds() {
requireLowerBounds();
requireUpperBounds();
return *this;
}
bool MinMaxLinearEquationSolverRequirements::requiresNoEndComponents() const {
return noEndComponents;
}

1
src/storm/solver/MinMaxLinearEquationSolverRequirements.h

@ -26,6 +26,7 @@ namespace storm {
MinMaxLinearEquationSolverRequirements& requireValidInitialScheduler();
MinMaxLinearEquationSolverRequirements& requireLowerBounds();
MinMaxLinearEquationSolverRequirements& requireUpperBounds();
MinMaxLinearEquationSolverRequirements& requireBounds();
bool requiresNoEndComponents() const;
bool requiresValidIntialScheduler() const;

7
src/storm/solver/NativeLinearEquationSolver.cpp

@ -497,7 +497,9 @@ namespace storm {
}
STORM_LOG_ASSERT(lowerDiff >= storm::utility::zero<ValueType>(), "Expected non-negative lower diff.");
STORM_LOG_ASSERT(upperDiff >= storm::utility::zero<ValueType>(), "Expected non-negative upper diff.");
STORM_LOG_TRACE("Lower difference: " << lowerDiff << ", upper difference: " << upperDiff << ".");
if (iterations % 100 == 0) {
STORM_LOG_TRACE("Iteration " << iterations << ": lower difference: " << lowerDiff << ", upper difference: " << upperDiff << ".");
}
if (doConvergenceCheck) {
// Now check if the process already converged within our precision. Note that we double the target
@ -632,8 +634,7 @@ namespace storm {
LinearEquationSolverRequirements requirements;
if (this->getSettings().getForceSoundness()) {
if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::Power) {
requirements.requireLowerBounds();
requirements.requireUpperBounds();
requirements.requireBounds();
} else {
STORM_LOG_WARN("Forcing soundness, but selecting a method other than the power iteration is not supported.");
}

81
src/storm/storage/ConsecutiveUint64DynamicPriorityQueue.h

@ -0,0 +1,81 @@
#pragma once
#include <algorithm>
#include <vector>
#include "storm/utility/macros.h"
namespace storm {
namespace storage {
template<typename Compare = std::less<uint64_t>>
class ConsecutiveUint64DynamicPriorityQueue {
public:
typedef uint64_t T;
typedef std::vector<T> Container;
private:
Container container;
Compare compare;
std::vector<uint64_t> positions;
public:
explicit ConsecutiveUint64DynamicPriorityQueue(uint64_t numberOfIntegers, Compare const& compare) : container(numberOfIntegers), compare(compare), positions(numberOfIntegers) {
std::iota(container.begin(), container.end(), 0);
}
void fix() {
std::make_heap(container.begin(), container.end(), compare);
}
void increase(uint64_t element) {
uint64_t position = positions[element];
if (position >= container.size()) {
return;
}
uint64_t parentPosition = (position - 1) / 2;
while (position > 0 && compare(container[parentPosition], container[position])) {
std::swap(container[parentPosition], container[position]);
std::swap(positions[container[parentPosition]], positions[container[position]]);
position = parentPosition;
parentPosition = (position - 1) / 2;
}
}
bool contains(uint64_t element) const {
return positions[element] < container.size();
}
bool empty() const {
return container.empty();
}
std::size_t size() const {
return container.size();
}
const T& top() const {
return container.front();
}
void push(uint64_t const& item) {
container.emplace_back(item);
std::push_heap(container.begin(), container.end(), compare);
}
void pop() {
std::pop_heap(container.begin(), container.end(), compare);
container.pop_back();
}
T popTop() {
T item = top();
pop();
return item;
}
};
}
}

99
src/storm/storage/VectorDynamicPriorityQueue.h

@ -1,99 +0,0 @@
#ifndef STORM_STORAGE_DYNAMICPRIORITYQUEUE_H_
#define STORM_STORAGE_DYNAMICPRIORITYQUEUE_H_
#include <algorithm>
#include <vector>
#include "storm/utility/macros.h"
namespace storm {
namespace storage {
template<typename Compare = std::less<uint64_t>>
class VectorDynamicPriorityQueue {
public:
typedef uint64_t T;
typedef std::vector<T> Container;
private:
Container container;
Compare compare;
std::vector<uint64_t> positions;
uint64_t upperBound;
uint64_t numberOfSortedEntriesAtBack;
uint64_t const NUMBER_OF_ENTRIES_TO_SORT = 100;
public:
explicit DynamicPriorityQueue(Compare const& compare, uint64_t upperBound) : container(), compare(compare), positions(upperBound) {
// Intentionally left empty
}
explicit DynamicPriorityQueue(Container&& container, Compare const& compare) : container(std::move(container)), compare(compare), positions(this->container.size()) {
sortAndUpdatePositions(container.begin(), container.end());
}
void fix() {
sortAndUpdatePositions(container.begin(), container.end());
}
bool empty() const {
return container.empty();
}
std::size_t size() const {
return container.size();
}
const T& top() const {
return container.front();
}
template<typename TemplateType>
void push(TemplateType&& item) {
if (this->empty() || container.back() < item) {
container.emplace_back(std::forward<TemplateType>(item));
} else {
}
}
void pop() {
container.pop_back();
--numberOfSortedEntriesAtBack;
if (numberOfSortedEntriesAtBack == 0) {
if (container.size() > NUMBER_OF_ENTRIES_TO_SORT) {
sortAndUpdatePositions(container.end() - NUMBER_OF_ENTRIES_TO_SORT, container.end());
numberOfSortedEntriesAtBack = NUMBER_OF_ENTRIES_TO_SORT;
} else {
sortAndUpdatePositions(container.begin(), container.end());
numberOfSortedEntriesAtBack = container.size();
}
}
}
T popTop() {
T item = top();
pop();
return item;
}
private:
void sortAndUpdatePositions(Container::const_iterator start, Container::const_iterator end) {
std::sort(start, end);
updatePositions(start, end);
}
void updatePositions(Container::const_iterator start, Container::const_iterator end) {
for (; start != end; ++start) {
position = std::distance(container.begin(), start);
positions[container[position]] = position;
}
}
};
}
}
#endif // STORM_STORAGE_DYNAMICPRIORITYQUEUE_H_
Loading…
Cancel
Save