Browse Source

changed handling of auxiliary memory in MinMaxSolver

Former-commit-id: 602833f39d
tempestpy_adaptions
TimQu 8 years ago
parent
commit
965d5b5e75
  1. 1
      src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp
  2. 1
      src/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp
  3. 13
      src/solver/MinMaxLinearEquationSolver.cpp
  4. 31
      src/solver/MinMaxLinearEquationSolver.h
  5. 138
      src/solver/StandardMinMaxLinearEquationSolver.cpp
  6. 23
      src/solver/StandardMinMaxLinearEquationSolver.h

1
src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp

@ -86,7 +86,6 @@ namespace storm {
}
std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = minMaxLinearEquationSolverFactory.create(aProbabilistic);
solver->allocateAuxMemory(storm::solver::MinMaxLinearEquationSolverOperation::SolveEquations);
// Perform the actual value iteration
// * loop until the step bound has been reached

1
src/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp

@ -307,7 +307,6 @@ namespace storm {
result->solver = minMaxSolverFactory.create(PS.toPS);
result->solver->setOptimizationDirection(storm::solver::OptimizationDirection::Maximize);
result->solver->setTrackScheduler(true);
result->solver->allocateAuxMemory(storm::solver::MinMaxLinearEquationSolverOperation::SolveEquations);
result->b.resize(PS.getNumberOfChoices());

13
src/solver/MinMaxLinearEquationSolver.cpp

@ -80,19 +80,10 @@ namespace storm {
}
template<typename ValueType>
bool MinMaxLinearEquationSolver<ValueType>::allocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const {
return false;
}
template<typename ValueType>
bool MinMaxLinearEquationSolver<ValueType>::deallocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const {
return false;
void MinMaxLinearEquationSolver<ValueType>::resetAuxiliaryData() const {
// Intentionally left empty.
}
template<typename ValueType>
bool MinMaxLinearEquationSolver<ValueType>::hasAuxMemory(MinMaxLinearEquationSolverOperation operation) const {
return false;
}
template<typename ValueType>
MinMaxLinearEquationSolverFactory<ValueType>::MinMaxLinearEquationSolverFactory(bool trackScheduler) : trackScheduler(trackScheduler) {

31
src/solver/MinMaxLinearEquationSolver.h

@ -22,10 +22,6 @@ namespace storm {
namespace solver {
enum class MinMaxLinearEquationSolverOperation {
SolveEquations, MultiplyRepeatedly
};
/*!
* A class representing the interface that all min-max linear equation solvers shall implement.
*/
@ -132,31 +128,10 @@ namespace storm {
*/
virtual bool getRelative() const = 0;
// Methods related to allocating/freeing auxiliary storage.
/*!
* Allocates auxiliary storage that can be used to perform the provided operation. Repeated calls to the
* corresponding function can then be run without allocating/deallocating this storage repeatedly.
* Note: Since the allocated storage is fit to the currently selected options of the solver, they must not
* be changed any more after allocating the auxiliary storage until the storage is deallocated again.
*
* @return True iff auxiliary storage was allocated.
*/
virtual bool allocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const;
/*!
* Destroys previously allocated auxiliary storage for the provided operation.
*
* @return True iff auxiliary storage was deallocated.
*/
virtual bool deallocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const;
/*!
* Checks whether the solver has allocated auxiliary storage for the provided operation.
*
* @return True iff auxiliary storage was previously allocated (and not yet deallocated).
/*
* Resets the auxiliary data that has been stored during previous calls of this solver
*/
virtual bool hasAuxMemory(MinMaxLinearEquationSolverOperation operation) const;
virtual void resetAuxiliaryData() const;
protected:

138
src/solver/StandardMinMaxLinearEquationSolver.cpp

@ -98,8 +98,11 @@ namespace storm {
// Create the initial scheduler.
std::vector<storm::storage::sparse::state_type> scheduler(this->A.getRowGroupCount());
// Create a vector for storing the right-hand side of the inner equation system.
std::vector<ValueType> subB(this->A.getRowGroupCount());
// Get a vector for storing the right-hand side of the inner equation system.
if(!auxiliaryData.rowGroupVector) {
auxiliaryData.rowGroupVector = std::make_unique<std::vector<ValueType>>(this->A.getRowGroupCount());
}
std::vector<ValueType>& subB = *auxiliaryData.rowGroupVector;
// Resolve the nondeterminism according to the current scheduler.
storm::storage::SparseMatrix<ValueType> submatrix = this->A.selectRowsFromRowGroups(scheduler, true);
@ -107,7 +110,7 @@ namespace storm {
storm::utility::vector::selectVectorValues<ValueType>(subB, scheduler, this->A.getRowGroupIndices(), b);
// Create a solver that we will use throughout the procedure. We will modify the matrix in each iteration.
solver = linearEquationSolverFactory->create(std::move(submatrix));
auto solver = linearEquationSolverFactory->create(std::move(submatrix));
solver->allocateAuxMemory(LinearEquationSolverOperation::SolveEquations);
Status status = Status::InProgress;
@ -166,8 +169,6 @@ namespace storm {
this->scheduler = std::make_unique<storm::storage::TotalScheduler>(std::move(scheduler));
}
solver.reset();
if(status == Status::Converged || status == Status::TerminatedEarly) {
return true;
} else{
@ -204,16 +205,21 @@ namespace storm {
template<typename ValueType>
bool StandardMinMaxLinearEquationSolver<ValueType>::solveEquationsValueIteration(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
if(solver == nullptr) {
solver = linearEquationSolverFactory->create(A);
if(!auxiliaryData.linEqSolver) {
auxiliaryData.linEqSolver = linearEquationSolverFactory->create(A);
}
bool allocatedAuxMemory = !this->hasAuxMemory(MinMaxLinearEquationSolverOperation::SolveEquations);
if (allocatedAuxMemory) {
this->allocateAuxMemory(MinMaxLinearEquationSolverOperation::SolveEquations);
if (!auxiliaryData.rowVector.get()) {
auxiliaryData.rowVector = std::make_unique<std::vector<ValueType>>(A.getRowCount());
}
std::vector<ValueType>& multiplyResult = *auxiliaryData.rowVector;
if (!auxiliaryData.rowGroupVector.get()) {
auxiliaryData.rowGroupVector = std::make_unique<std::vector<ValueType>>(A.getRowGroupCount());
}
std::vector<ValueType>* newX = auxiliaryData.rowGroupVector.get();
std::vector<ValueType>* currentX = &x;
std::vector<ValueType>* newX = auxiliarySolvingVectorMemory.get();
// Proceed with the iterations as long as the method did not converge or reach the maximum number of iterations.
uint64_t iterations = 0;
@ -221,10 +227,10 @@ namespace storm {
Status status = Status::InProgress;
while (status == Status::InProgress) {
// Compute x' = A*x + b.
solver->multiply(*currentX, &b, *auxiliarySolvingMultiplyMemory);
auxiliaryData.linEqSolver->multiply(*currentX, &b, multiplyResult);
// Reduce the vector x' by applying min/max for all non-deterministic choices.
storm::utility::vector::reduceVectorMinOrMax(dir, *auxiliarySolvingMultiplyMemory, *newX, this->A.getRowGroupIndices());
storm::utility::vector::reduceVectorMinOrMax(dir, multiplyResult, *newX, this->A.getRowGroupIndices());
// Determine whether the method converged.
if (storm::utility::vector::equalModuloPrecision<ValueType>(*currentX, *newX, this->getSettings().getPrecision(), this->getSettings().getRelativeTerminationCriterion())) {
@ -242,27 +248,20 @@ namespace storm {
// If we performed an odd number of iterations, we need to swap the x and currentX, because the newest result
// is currently stored in currentX, but x is the output vector.
if (currentX == auxiliarySolvingVectorMemory.get()) {
if (currentX == auxiliaryData.rowGroupVector.get()) {
std::swap(x, *currentX);
}
// If requested, we store the scheduler for retrieval.
if (this->isTrackSchedulerSet()) {
if(iterations==0){ //may happen due to custom termination condition. Then we need to compute x'= A*x+b
solver->multiply(x, &b, *auxiliarySolvingMultiplyMemory);
auxiliaryData.linEqSolver->multiply(x, &b, multiplyResult);
}
std::vector<storm::storage::sparse::state_type> choices(this->A.getRowGroupCount());
// Reduce the multiplyResult and keep track of the choices made
storm::utility::vector::reduceVectorMinOrMax(dir, *auxiliarySolvingMultiplyMemory, x, this->A.getRowGroupIndices(), &choices);
storm::utility::vector::reduceVectorMinOrMax(dir, multiplyResult, x, this->A.getRowGroupIndices(), &choices);
this->scheduler = std::make_unique<storm::storage::TotalScheduler>(std::move(choices));
}
// If we allocated auxiliary memory, we need to dispose of it now.
if (allocatedAuxMemory) {
this->deallocateAuxMemory(MinMaxLinearEquationSolverOperation::SolveEquations);
}
if(status == Status::Converged || status == Status::TerminatedEarly) {
return true;
@ -273,26 +272,21 @@ namespace storm {
template<typename ValueType>
void StandardMinMaxLinearEquationSolver<ValueType>::repeatedMultiply(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType>* b, uint_fast64_t n) const {
bool allocatedAuxMemory = !this->hasAuxMemory(MinMaxLinearEquationSolverOperation::MultiplyRepeatedly);
if (allocatedAuxMemory) {
this->allocateAuxMemory(MinMaxLinearEquationSolverOperation::MultiplyRepeatedly);
if(!auxiliaryData.linEqSolver) {
auxiliaryData.linEqSolver = linearEquationSolverFactory->create(A);
}
if(solver == nullptr) {
solver = linearEquationSolverFactory->create(A);
if (!auxiliaryData.rowVector.get()) {
auxiliaryData.rowVector = std::make_unique<std::vector<ValueType>>(A.getRowCount());
}
std::vector<ValueType>& multiplyResult = *auxiliaryData.rowVector;
for (uint64_t i = 0; i < n; ++i) {
solver->multiply(x, b, *auxiliaryRepeatedMultiplyMemory);
auxiliaryData.linEqSolver->multiply(x, b, multiplyResult);
// Reduce the vector x' by applying min/max for all non-deterministic choices as given by the topmost
// element of the min/max operator stack.
storm::utility::vector::reduceVectorMinOrMax(dir, *auxiliaryRepeatedMultiplyMemory, x, this->A.getRowGroupIndices());
}
// If we allocated auxiliary memory, we need to dispose of it now.
if (allocatedAuxMemory) {
this->deallocateAuxMemory(MinMaxLinearEquationSolverOperation::MultiplyRepeatedly);
storm::utility::vector::reduceVectorMinOrMax(dir, multiplyResult, x, this->A.getRowGroupIndices());
}
}
@ -325,77 +319,17 @@ namespace storm {
}
template<typename ValueType>
StandardMinMaxLinearEquationSolverSettings<ValueType>& StandardMinMaxLinearEquationSolver<ValueType>::getSettings() {
return settings;
void StandardMinMaxLinearEquationSolver<ValueType>::setSettings(StandardMinMaxLinearEquationSolverSettings<ValueType> const& newSettings) {
settings = newSettings;
}
template<typename ValueType>
bool StandardMinMaxLinearEquationSolver<ValueType>::allocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const {
bool result = false;
if (operation == MinMaxLinearEquationSolverOperation::SolveEquations) {
if (this->getSettings().getSolutionMethod() == StandardMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration) {
if (!auxiliarySolvingMultiplyMemory) {
result = true;
auxiliarySolvingMultiplyMemory = std::make_unique<std::vector<ValueType>>(this->A.getRowCount());
}
if (!auxiliarySolvingVectorMemory) {
result = true;
auxiliarySolvingVectorMemory = std::make_unique<std::vector<ValueType>>(this->A.getRowGroupCount());
}
} else if (this->getSettings().getSolutionMethod() == StandardMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::PolicyIteration) {
// Nothing to do in this case.
} else {
STORM_LOG_ASSERT(false, "Cannot allocate aux storage for this method.");
}
} else {
if (!auxiliaryRepeatedMultiplyMemory) {
result = true;
auxiliaryRepeatedMultiplyMemory = std::make_unique<std::vector<ValueType>>(this->A.getRowCount());
}
}
return result;
void StandardMinMaxLinearEquationSolver<ValueType>::resetAuxiliaryData() const {
auxiliaryData.linEqSolver.reset();
auxiliaryData.rowVector.reset();
auxiliaryData.rowGroupVector.reset();
}
template<typename ValueType>
bool StandardMinMaxLinearEquationSolver<ValueType>::deallocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const {
bool result = false;
if (operation == MinMaxLinearEquationSolverOperation::SolveEquations) {
if (this->getSettings().getSolutionMethod() == StandardMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration) {
if (auxiliarySolvingMultiplyMemory) {
result = true;
auxiliarySolvingMultiplyMemory.reset();
}
if (auxiliarySolvingVectorMemory) {
result = true;
auxiliarySolvingVectorMemory.reset();
}
} else if (this->getSettings().getSolutionMethod() == StandardMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::PolicyIteration) {
// Nothing to do in this case.
} else {
STORM_LOG_ASSERT(false, "Cannot allocate aux storage for this method.");
}
} else {
if (auxiliaryRepeatedMultiplyMemory) {
result = true;
auxiliaryRepeatedMultiplyMemory.reset();
}
}
return result;
}
template<typename ValueType>
bool StandardMinMaxLinearEquationSolver<ValueType>::hasAuxMemory(MinMaxLinearEquationSolverOperation operation) const {
if (operation == MinMaxLinearEquationSolverOperation::SolveEquations) {
if (this->getSettings().getSolutionMethod() == StandardMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration) {
return auxiliarySolvingMultiplyMemory && auxiliarySolvingVectorMemory;
} else {
return false;
}
} else {
return static_cast<bool>(auxiliaryRepeatedMultiplyMemory);
}
}
template<typename ValueType>
StandardMinMaxLinearEquationSolverFactory<ValueType>::StandardMinMaxLinearEquationSolverFactory(bool trackScheduler) : MinMaxLinearEquationSolverFactory<ValueType>(trackScheduler), linearEquationSolverFactory(nullptr) {
// Intentionally left empty.

23
src/solver/StandardMinMaxLinearEquationSolver.h

@ -11,6 +11,8 @@ namespace storm {
public:
StandardMinMaxLinearEquationSolverSettings();
StandardMinMaxLinearEquationSolverSettings<ValueType>& operator=(StandardMinMaxLinearEquationSolverSettings<ValueType> const& other) = default;
enum class SolutionMethod {
ValueIteration, PolicyIteration
};
@ -42,11 +44,9 @@ namespace storm {
virtual void repeatedMultiply(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType>* b, uint_fast64_t n) const override;
StandardMinMaxLinearEquationSolverSettings<ValueType> const& getSettings() const;
StandardMinMaxLinearEquationSolverSettings<ValueType>& getSettings();
void setSettings(StandardMinMaxLinearEquationSolverSettings<ValueType> const& newSettings);
virtual bool allocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const override;
virtual bool deallocateAuxMemory(MinMaxLinearEquationSolverOperation operation) const override;
virtual bool hasAuxMemory(MinMaxLinearEquationSolverOperation operation) const override;
virtual void resetAuxiliaryData() const override;
virtual ValueType getPrecision() const override;
virtual bool getRelative() const override;
@ -59,6 +59,14 @@ namespace storm {
enum class Status {
Converged, TerminatedEarly, MaximalIterationsExceeded, InProgress
};
struct AuxiliaryData {
std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> linEqSolver;
std::unique_ptr<std::vector<ValueType>> rowVector; // A.rowCount() entries
std::unique_ptr<std::vector<ValueType>> rowGroupVector; // A.rowGroupCount() entries
};
mutable AuxiliaryData auxiliaryData;
Status updateStatusIfNotConverged(Status status, std::vector<ValueType> const& x, uint64_t iterations) const;
void reportStatus(Status status, uint64_t iterations) const;
@ -68,7 +76,6 @@ namespace storm {
/// The factory used to obtain linear equation solvers.
std::unique_ptr<LinearEquationSolverFactory<ValueType>> linearEquationSolverFactory;
mutable std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver;
// If the solver takes posession of the matrix, we store the moved matrix in this member, so it gets deleted
// when the solver is destructed.
@ -78,12 +85,6 @@ namespace storm {
// the reference refers to localA.
storm::storage::SparseMatrix<ValueType> const& A;
// Auxiliary memory for equation solving.
mutable std::unique_ptr<std::vector<ValueType>> auxiliarySolvingMultiplyMemory;
mutable std::unique_ptr<std::vector<ValueType>> auxiliarySolvingVectorMemory;
// Auxiliary memory for repeated matrix-vector multiplication.
mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRepeatedMultiplyMemory;
};
template<typename ValueType>

Loading…
Cancel
Save