You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
7.4 KiB
186 lines
7.4 KiB
/*
|
|
* GmmxxDtmcPrctlModelChecker.h
|
|
*
|
|
* Created on: 06.12.2012
|
|
* Author: Christian Dehnert
|
|
*/
|
|
|
|
#ifndef STORM_MODELCHECKER_PRCTL_GMMXXMDPPRCTLMODELCHECKER_H_
|
|
#define STORM_MODELCHECKER_PRCTL_GMMXXMDPPRCTLMODELCHECKER_H_
|
|
|
|
#include "src/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|
#include "src/adapters/GmmxxAdapter.h"
|
|
|
|
#include "gmm/gmm_matrix.h"
|
|
#include "gmm/gmm_iter_solvers.h"
|
|
|
|
#include <cmath>
|
|
|
|
namespace storm {
|
|
namespace modelchecker {
|
|
namespace prctl {
|
|
|
|
/*
|
|
* An implementation of the SparseMdpPrctlModelChecker interface that uses gmm++ as the solving backend.
|
|
*/
|
|
template <class Type>
|
|
class GmmxxMdpPrctlModelChecker : public SparseMdpPrctlModelChecker<Type> {
|
|
|
|
public:
|
|
/*!
|
|
* Constructs a GmmxxMdpPrctlModelChecker with the given model.
|
|
*
|
|
* @param model The MDP to be checked.
|
|
*/
|
|
explicit GmmxxMdpPrctlModelChecker(storm::models::Mdp<Type> const& model) : SparseMdpPrctlModelChecker<Type>(model) {
|
|
// Intentionally left empty.
|
|
}
|
|
|
|
/*!
|
|
* Copy constructs a GmmxxDtmcPrctlModelChecker from the given model checker. In particular, this means that the newly
|
|
* constructed model checker will have the model of the given model checker as its associated model.
|
|
*/
|
|
explicit GmmxxMdpPrctlModelChecker(storm::modelchecker::prctl::GmmxxMdpPrctlModelChecker<Type> const& modelchecker) : SparseMdpPrctlModelChecker<Type>(modelchecker) {
|
|
// Intentionally left empty.
|
|
}
|
|
|
|
/*!
|
|
* Virtual destructor. Needs to be virtual, because this class has virtual methods.
|
|
*/
|
|
virtual ~GmmxxMdpPrctlModelChecker() {
|
|
// Intentionally left empty.
|
|
}
|
|
|
|
private:
|
|
|
|
/*!
|
|
* Performs (repeated) matrix-vector multiplication with the given parameters, i.e. computes x[i+1] = A*x[i] + b
|
|
* until x[n], where x[0] = x.
|
|
*
|
|
* @param A The matrix that is to be multiplied against the vector.
|
|
* @param x The initial vector that is to be multiplied against the matrix. This is also the output parameter,
|
|
* i.e. after the method returns, this vector will contain the computed values.
|
|
* @param nondeterministicChoiceIndices The assignment of states to their rows in the matrix.
|
|
* @param b If not null, this vector is being added to the result after each matrix-vector multiplication.
|
|
* @param n Specifies the number of iterations the matrix-vector multiplication is performed.
|
|
* @returns The result of the repeated matrix-vector multiplication as the content of the parameter vector.
|
|
*/
|
|
virtual void performMatrixVectorMultiplication(storm::storage::SparseMatrix<Type> const& A, std::vector<Type>& x, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<Type>* b = nullptr, uint_fast64_t n = 1) const {
|
|
// Transform the transition probability matrix to the gmm++ format to use its arithmetic.
|
|
gmm::csr_matrix<Type>* gmmxxMatrix = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<Type>(A);
|
|
|
|
// Create vector for result of multiplication, which is reduced to the result vector after
|
|
// each multiplication.
|
|
std::vector<Type> multiplyResult(A.getRowCount());
|
|
|
|
// Now perform matrix-vector multiplication as long as we meet the bound of the formula.
|
|
for (uint_fast64_t i = 0; i < n; ++i) {
|
|
gmm::mult(*gmmxxMatrix, x, multiplyResult);
|
|
|
|
if (b != nullptr) {
|
|
gmm::add(*b, multiplyResult);
|
|
}
|
|
|
|
if (this->minimumOperatorStack.top()) {
|
|
storm::utility::vector::reduceVectorMin(multiplyResult, x, nondeterministicChoiceIndices);
|
|
} else {
|
|
storm::utility::vector::reduceVectorMax(multiplyResult, x, nondeterministicChoiceIndices);
|
|
}
|
|
}
|
|
|
|
// Delete intermediate results and return result.
|
|
delete gmmxxMatrix;
|
|
}
|
|
|
|
/*!
|
|
* Solves the given equation system under the given parameters using the power method.
|
|
*
|
|
* @param minimize If set, all choices are resolved such that the solution value becomes minimal and maximal otherwise.
|
|
* @param A The matrix A specifying the coefficients of the equations.
|
|
* @param x The vector x for which to solve the equations. The initial value of the elements of
|
|
* this vector are used as the initial guess and might thus influence performance and convergence.
|
|
* @param b The vector b specifying the values on the right-hand-sides of the equations.
|
|
* @return The solution of the system of linear equations in form of the elements of the vector
|
|
* x.
|
|
*/
|
|
void solveEquationSystem(bool minimize, storm::storage::SparseMatrix<Type> const& A, std::vector<Type>& x, std::vector<Type> const& b, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<uint_fast64_t>* takenChoices = nullptr) const override {
|
|
// Get the settings object to customize solving.
|
|
storm::settings::Settings* s = storm::settings::instance();
|
|
|
|
// Get relevant user-defined settings for solving the equations.
|
|
double precision = s->get<double>("precision");
|
|
unsigned maxIterations = s->get<unsigned>("maxiter");
|
|
bool relative = s->get<bool>("relative");
|
|
|
|
// Transform the transition probability matrix to the gmm++ format to use its arithmetic.
|
|
gmm::csr_matrix<Type>* gmmxxMatrix = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<Type>(A);
|
|
|
|
// Set up the environment for the power method.
|
|
std::vector<Type> multiplyResult(A.getRowCount());
|
|
std::vector<Type>* currentX = &x;
|
|
std::vector<Type>* newX = new std::vector<Type>(x.size());
|
|
std::vector<Type>* swap = nullptr;
|
|
uint_fast64_t iterations = 0;
|
|
bool converged = false;
|
|
|
|
// Proceed with the iterations as long as the method did not converge or reach the user-specified maximum number
|
|
// of iterations.
|
|
while (!converged && iterations < maxIterations) {
|
|
std::cout << "iter: " << iterations << std::endl;
|
|
// Compute x' = A*x + b.
|
|
gmm::mult(*gmmxxMatrix, *currentX, multiplyResult);
|
|
gmm::add(b, multiplyResult);
|
|
|
|
// Reduce the vector x' by applying min/max for all non-deterministic choices.
|
|
if (minimize) {
|
|
storm::utility::vector::reduceVectorMin(multiplyResult, *newX, nondeterministicChoiceIndices);
|
|
} else {
|
|
storm::utility::vector::reduceVectorMax(multiplyResult, *newX, nondeterministicChoiceIndices);
|
|
}
|
|
|
|
// Determine whether the method converged.
|
|
converged = storm::utility::vector::equalModuloPrecision(*currentX, *newX, precision, relative);
|
|
|
|
if (!converged) {
|
|
for (uint_fast64_t i = 0; i < newX->size(); ++i) {
|
|
std::cout << (*currentX)[i] << " vs. " << (*newX)[i] << std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
// Update environment variables.
|
|
swap = currentX;
|
|
currentX = newX;
|
|
newX = swap;
|
|
++iterations;
|
|
}
|
|
|
|
// If we were requested to record the taken choices, we have to construct the vector now.
|
|
if (takenChoices != nullptr) {
|
|
this->computeTakenChoices(minimize, multiplyResult, *takenChoices, nondeterministicChoiceIndices);
|
|
}
|
|
|
|
// 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 (iterations % 2 == 1) {
|
|
std::swap(x, *currentX);
|
|
delete currentX;
|
|
} else {
|
|
delete newX;
|
|
}
|
|
delete gmmxxMatrix;
|
|
|
|
// Check if the solver converged and issue a warning otherwise.
|
|
if (converged) {
|
|
LOG4CPLUS_INFO(logger, "Iterative solver converged after " << iterations << " iterations.");
|
|
} else {
|
|
LOG4CPLUS_WARN(logger, "Iterative solver did not converge after " << iterations << " iterations.");
|
|
}
|
|
}
|
|
};
|
|
|
|
} //namespace prctl
|
|
} //namespace modelchecker
|
|
} //namespace storm
|
|
|
|
#endif /* STORM_MODELCHECKER_PRCTL_GMMXXMDPPRCTLMODELCHECKER_H_ */
|