Browse Source

Some cleanup in storm.cpp. Refactored and commented the utility module for vector operations.

tempestpy_adaptions
dehnert 12 years ago
parent
commit
64b883f695
  1. 4
      src/modelchecker/GmmxxDtmcPrctlModelChecker.h
  2. 21
      src/modelchecker/GmmxxMdpPrctlModelChecker.h
  3. 26
      src/modelchecker/SparseDtmcPrctlModelChecker.h
  4. 43
      src/modelchecker/SparseMdpPrctlModelChecker.h
  5. 160
      src/storm.cpp
  6. 212
      src/utility/Vector.h
  7. 2
      src/utility/graph.h
  8. 281
      src/utility/vector.h

4
src/modelchecker/GmmxxDtmcPrctlModelChecker.h

@ -34,7 +34,7 @@ public:
* *
* @param model The DTMC to be checked. * @param model The DTMC to be checked.
*/ */
explicit GmmxxDtmcPrctlModelChecker(storm::models::Dtmc<Type>& dtmc) : SparseDtmcPrctlModelChecker<Type>(dtmc) {
explicit GmmxxDtmcPrctlModelChecker(storm::models::Dtmc<Type> const& dtmc) : SparseDtmcPrctlModelChecker<Type>(dtmc) {
// Intentionally left empty. // Intentionally left empty.
} }
@ -277,7 +277,7 @@ private:
xCurrent = swap; xCurrent = swap;
// Now check if the process already converged within our precision. // Now check if the process already converged within our precision.
converged = storm::utility::equalModuloPrecision(*xCurrent, *xNext, precision, relative);
converged = storm::utility::vector::equalModuloPrecision(*xCurrent, *xNext, precision, relative);
// Increase iteration count so we can abort if convergence is too slow. // Increase iteration count so we can abort if convergence is too slow.
++iterationCount; ++iterationCount;

21
src/modelchecker/GmmxxMdpPrctlModelChecker.h

@ -52,6 +52,17 @@ public:
private: 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 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<Type>* b = nullptr, uint_fast64_t n = 1) const { virtual void performMatrixVectorMultiplication(storm::storage::SparseMatrix<Type> const& A, std::vector<Type>& x, std::vector<Type>* b = nullptr, uint_fast64_t n = 1) const {
// Get the starting row indices for the non-deterministic choices to reduce the resulting // Get the starting row indices for the non-deterministic choices to reduce the resulting
// vector properly. // vector properly.
@ -74,9 +85,9 @@ private:
} }
if (this->minimumOperatorStack.top()) { if (this->minimumOperatorStack.top()) {
storm::utility::reduceVectorMin(multiplyResult, &x, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMin(multiplyResult, x, nondeterministicChoiceIndices);
} else { } else {
storm::utility::reduceVectorMax(multiplyResult, &x, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMax(multiplyResult, x, nondeterministicChoiceIndices);
} }
} }
@ -124,13 +135,13 @@ private:
// Reduce the vector x' by applying min/max for all non-deterministic choices. // Reduce the vector x' by applying min/max for all non-deterministic choices.
if (this->minimumOperatorStack.top()) { if (this->minimumOperatorStack.top()) {
storm::utility::reduceVectorMin(multiplyResult, newX, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMin(multiplyResult, *newX, nondeterministicChoiceIndices);
} else { } else {
storm::utility::reduceVectorMax(multiplyResult, newX, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMax(multiplyResult, *newX, nondeterministicChoiceIndices);
} }
// Determine whether the method converged. // Determine whether the method converged.
converged = storm::utility::equalModuloPrecision(*currentX, *newX, precision, relative);
converged = storm::utility::vector::equalModuloPrecision(*currentX, *newX, precision, relative);
// Update environment variables. // Update environment variables.
swap = currentX; swap = currentX;

26
src/modelchecker/SparseDtmcPrctlModelChecker.h

@ -96,7 +96,7 @@ public:
// Create the vector with which to multiply. // Create the vector with which to multiply.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates()); std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
storm::utility::setVectorValues(result, *rightStates, storm::utility::constGetOne<Type>());
storm::utility::vector::setVectorValues(*result, *rightStates, storm::utility::constGetOne<Type>());
// Perform the matrix vector multiplication as often as required by the formula bound. // Perform the matrix vector multiplication as often as required by the formula bound.
this->performMatrixVectorMultiplication(tmpMatrix, *result, nullptr, formula.getBound()); this->performMatrixVectorMultiplication(tmpMatrix, *result, nullptr, formula.getBound());
@ -124,7 +124,7 @@ public:
// Create the vector with which to multiply and initialize it correctly. // Create the vector with which to multiply and initialize it correctly.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates()); std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
storm::utility::setVectorValues(result, *nextStates, storm::utility::constGetOne<Type>());
storm::utility::vector::setVectorValues(*result, *nextStates, storm::utility::constGetOne<Type>());
// Delete obsolete intermediate. // Delete obsolete intermediate.
delete nextStates; delete nextStates;
@ -187,7 +187,7 @@ public:
std::vector<Type>* result = this->checkEventually(temporaryEventuallyFormula, qualitative); std::vector<Type>* result = this->checkEventually(temporaryEventuallyFormula, qualitative);
// Now subtract the resulting vector from the constant one vector to obtain final result. // Now subtract the resulting vector from the constant one vector to obtain final result.
storm::utility::subtractFromConstantOneVector(result);
storm::utility::vector::subtractFromConstantOneVector(*result);
return result; return result;
} }
@ -248,16 +248,16 @@ public:
this->solveEquationSystem(submatrix, x, b); this->solveEquationSystem(submatrix, x, b);
// Set values of resulting vector according to result. // Set values of resulting vector according to result.
storm::utility::setVectorValues<Type>(result, maybeStates, x);
storm::utility::vector::setVectorValues<Type>(*result, maybeStates, x);
} else if (qualitative) { } else if (qualitative) {
// If we only need a qualitative result, we can safely assume that the results will only be compared to // If we only need a qualitative result, we can safely assume that the results will only be compared to
// bounds which are either 0 or 1. Setting the value to 0.5 is thus safe. // bounds which are either 0 or 1. Setting the value to 0.5 is thus safe.
storm::utility::setVectorValues<Type>(result, maybeStates, Type(0.5));
storm::utility::vector::setVectorValues<Type>(*result, maybeStates, Type(0.5));
} }
// Set values of resulting vector that are known exactly. // Set values of resulting vector that are known exactly.
storm::utility::setVectorValues<Type>(result, statesWithProbability0, storm::utility::constGetZero<Type>());
storm::utility::setVectorValues<Type>(result, statesWithProbability1, storm::utility::constGetOne<Type>());
storm::utility::vector::setVectorValues<Type>(*result, statesWithProbability0, storm::utility::constGetZero<Type>());
storm::utility::vector::setVectorValues<Type>(*result, statesWithProbability1, storm::utility::constGetOne<Type>());
return result; return result;
} }
@ -384,7 +384,7 @@ public:
// side to the vector resulting from summing the rows of the pointwise product // side to the vector resulting from summing the rows of the pointwise product
// of the transition probability matrix and the transition reward matrix. // of the transition probability matrix and the transition reward matrix.
std::vector<Type> pointwiseProductRowSumVector = this->getModel().getTransitionMatrix()->getPointwiseProductRowSumVector(*this->getModel().getTransitionRewardMatrix()); std::vector<Type> pointwiseProductRowSumVector = this->getModel().getTransitionMatrix()->getPointwiseProductRowSumVector(*this->getModel().getTransitionRewardMatrix());
storm::utility::selectVectorValues(&b, maybeStates, pointwiseProductRowSumVector);
storm::utility::vector::selectVectorValues(b, maybeStates, pointwiseProductRowSumVector);
if (this->getModel().hasStateRewards()) { if (this->getModel().hasStateRewards()) {
// If a state-based reward model is also available, we need to add this vector // If a state-based reward model is also available, we need to add this vector
@ -392,7 +392,7 @@ public:
// that we still consider (i.e. maybeStates), we need to extract these values // that we still consider (i.e. maybeStates), we need to extract these values
// first. // first.
std::vector<Type> subStateRewards(maybeStatesSetBitCount); std::vector<Type> subStateRewards(maybeStatesSetBitCount);
storm::utility::selectVectorValues(&subStateRewards, maybeStates, *this->getModel().getStateRewardVector());
storm::utility::vector::selectVectorValues(subStateRewards, maybeStates, *this->getModel().getStateRewardVector());
gmm::add(subStateRewards, b); gmm::add(subStateRewards, b);
} }
} else { } else {
@ -400,19 +400,19 @@ public:
// right-hand side. As the state reward vector contains entries not just for the // right-hand side. As the state reward vector contains entries not just for the
// states that we still consider (i.e. maybeStates), we need to extract these values // states that we still consider (i.e. maybeStates), we need to extract these values
// first. // first.
storm::utility::selectVectorValues(&b, maybeStates, *this->getModel().getStateRewardVector());
storm::utility::vector::selectVectorValues(b, maybeStates, *this->getModel().getStateRewardVector());
} }
// Now solve the resulting equation system. // Now solve the resulting equation system.
this->solveEquationSystem(submatrix, x, b); this->solveEquationSystem(submatrix, x, b);
// Set values of resulting vector according to result. // Set values of resulting vector according to result.
storm::utility::setVectorValues<Type>(result, maybeStates, x);
storm::utility::vector::setVectorValues<Type>(*result, maybeStates, x);
} }
// Set values of resulting vector that are known exactly. // Set values of resulting vector that are known exactly.
storm::utility::setVectorValues(result, *targetStates, storm::utility::constGetZero<Type>());
storm::utility::setVectorValues(result, infinityStates, storm::utility::constGetInfinity<Type>());
storm::utility::vector::setVectorValues(*result, *targetStates, storm::utility::constGetZero<Type>());
storm::utility::vector::setVectorValues(*result, infinityStates, storm::utility::constGetInfinity<Type>());
// Delete temporary storages and return result. // Delete temporary storages and return result.
delete targetStates; delete targetStates;

43
src/modelchecker/SparseMdpPrctlModelChecker.h

@ -102,7 +102,7 @@ public:
// Create the vector with which to multiply. // Create the vector with which to multiply.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates()); std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
storm::utility::setVectorValues(result, *rightStates, storm::utility::constGetOne<Type>());
storm::utility::vector::setVectorValues(*result, *rightStates, storm::utility::constGetOne<Type>());
this->performMatrixVectorMultiplication(*this->getModel().getTransitionMatrix(), *result, nullptr, formula.getBound()); this->performMatrixVectorMultiplication(*this->getModel().getTransitionMatrix(), *result, nullptr, formula.getBound());
@ -129,7 +129,7 @@ public:
// Create the vector with which to multiply and initialize it correctly. // Create the vector with which to multiply and initialize it correctly.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates()); std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
storm::utility::setVectorValues(result, *nextStates, storm::utility::constGetOne<Type>());
storm::utility::vector::setVectorValues(*result, *nextStates, storm::utility::constGetOne<Type>());
// Delete obsolete sub-result. // Delete obsolete sub-result.
delete nextStates; delete nextStates;
@ -191,7 +191,7 @@ public:
std::vector<Type>* result = this->checkEventually(temporaryEventuallyFormula, qualitative); std::vector<Type>* result = this->checkEventually(temporaryEventuallyFormula, qualitative);
// Now subtract the resulting vector from the constant one vector to obtain final result. // Now subtract the resulting vector from the constant one vector to obtain final result.
storm::utility::subtractFromConstantOneVector(result);
storm::utility::vector::subtractFromConstantOneVector(*result);
return result; return result;
} }
@ -255,12 +255,12 @@ public:
this->solveEquationSystem(submatrix, x, b, subNondeterministicChoiceIndices); this->solveEquationSystem(submatrix, x, b, subNondeterministicChoiceIndices);
// Set values of resulting vector according to result. // Set values of resulting vector according to result.
storm::utility::setVectorValues<Type>(result, maybeStates, x);
storm::utility::vector::setVectorValues<Type>(*result, maybeStates, x);
} }
// Set values of resulting vector that are known exactly. // Set values of resulting vector that are known exactly.
storm::utility::setVectorValues<Type>(result, statesWithProbability0, storm::utility::constGetZero<Type>());
storm::utility::setVectorValues<Type>(result, statesWithProbability1, storm::utility::constGetOne<Type>());
storm::utility::vector::setVectorValues<Type>(*result, statesWithProbability0, storm::utility::constGetZero<Type>());
storm::utility::vector::setVectorValues<Type>(*result, statesWithProbability1, storm::utility::constGetOne<Type>());
return result; return result;
} }
@ -396,36 +396,35 @@ public:
// side to the vector resulting from summing the rows of the pointwise product // side to the vector resulting from summing the rows of the pointwise product
// of the transition probability matrix and the transition reward matrix. // of the transition probability matrix and the transition reward matrix.
std::vector<Type> pointwiseProductRowSumVector = this->getModel().getTransitionMatrix()->getPointwiseProductRowSumVector(*this->getModel().getTransitionRewardMatrix()); std::vector<Type> pointwiseProductRowSumVector = this->getModel().getTransitionMatrix()->getPointwiseProductRowSumVector(*this->getModel().getTransitionRewardMatrix());
storm::utility::selectVectorValues(&b, maybeStates, *this->getModel().getNondeterministicChoiceIndices(), pointwiseProductRowSumVector);
storm::utility::vector::selectVectorValues(b, maybeStates, *this->getModel().getNondeterministicChoiceIndices(), pointwiseProductRowSumVector);
if (this->getModel().hasStateRewards()) { if (this->getModel().hasStateRewards()) {
// If a state-based reward model is also available, we need to add this vector // If a state-based reward model is also available, we need to add this vector
// as well. As the state reward vector contains entries not just for the states // as well. As the state reward vector contains entries not just for the states
// that we still consider (i.e. maybeStates), we need to extract these values // that we still consider (i.e. maybeStates), we need to extract these values
// first. // first.
std::vector<Type>* subStateRewards = new std::vector<Type>(b.size());
storm::utility::selectVectorValuesRepeatedly(subStateRewards, maybeStates, *this->getModel().getNondeterministicChoiceIndices(), *this->getModel().getStateRewardVector());
gmm::add(*subStateRewards, b);
delete subStateRewards;
std::vector<Type> subStateRewards(b.size());
storm::utility::vector::selectVectorValuesRepeatedly(subStateRewards, maybeStates, *this->getModel().getNondeterministicChoiceIndices(), *this->getModel().getStateRewardVector());
gmm::add(subStateRewards, b);
} }
} else { } else {
// If only a state-based reward model is available, we take this vector as the // If only a state-based reward model is available, we take this vector as the
// right-hand side. As the state reward vector contains entries not just for the // right-hand side. As the state reward vector contains entries not just for the
// states that we still consider (i.e. maybeStates), we need to extract these values // states that we still consider (i.e. maybeStates), we need to extract these values
// first. // first.
storm::utility::selectVectorValuesRepeatedly(&b, maybeStates, *this->getModel().getNondeterministicChoiceIndices(), *this->getModel().getStateRewardVector());
storm::utility::vector::selectVectorValuesRepeatedly(b, maybeStates, *this->getModel().getNondeterministicChoiceIndices(), *this->getModel().getStateRewardVector());
} }
// Solve the corresponding system of equations. // Solve the corresponding system of equations.
this->solveEquationSystem(submatrix, x, b, subNondeterministicChoiceIndices); this->solveEquationSystem(submatrix, x, b, subNondeterministicChoiceIndices);
// Set values of resulting vector according to result. // Set values of resulting vector according to result.
storm::utility::setVectorValues<Type>(result, maybeStates, x);
storm::utility::vector::setVectorValues<Type>(*result, maybeStates, x);
} }
// Set values of resulting vector that are known exactly. // Set values of resulting vector that are known exactly.
storm::utility::setVectorValues(result, *targetStates, storm::utility::constGetZero<Type>());
storm::utility::setVectorValues(result, infinityStates, storm::utility::constGetInfinity<Type>());
storm::utility::vector::setVectorValues(*result, *targetStates, storm::utility::constGetZero<Type>());
storm::utility::vector::setVectorValues(*result, infinityStates, storm::utility::constGetInfinity<Type>());
// Delete temporary storages and return result. // Delete temporary storages and return result.
delete targetStates; delete targetStates;
@ -466,15 +465,15 @@ private:
// Add b if it is non-null. // Add b if it is non-null.
if (b != nullptr) { if (b != nullptr) {
storm::utility::addVectors(multiplyResult, *b);
storm::utility::vector::addVectorsInPlace(multiplyResult, *b);
} }
// Reduce the vector x' by applying min/max for all non-deterministic choices as given by the topmost // 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. // element of the min/max operator stack.
if (this->minimumOperatorStack.top()) { if (this->minimumOperatorStack.top()) {
storm::utility::reduceVectorMin(multiplyResult, &x, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMin(multiplyResult, x, nondeterministicChoiceIndices);
} else { } else {
storm::utility::reduceVectorMax(multiplyResult, &x, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMax(multiplyResult, x, nondeterministicChoiceIndices);
} }
} }
} }
@ -510,18 +509,18 @@ private:
while (!converged && iterations < maxIterations) { while (!converged && iterations < maxIterations) {
// Compute x' = A*x + b. // Compute x' = A*x + b.
A.multiplyWithVector(*currentX, multiplyResult); A.multiplyWithVector(*currentX, multiplyResult);
storm::utility::addVectors(multiplyResult, b);
storm::utility::vector::addVectorsInPlace(multiplyResult, b);
// Reduce the vector x' by applying min/max for all non-deterministic choices as given by the topmost // 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. // element of the min/max operator stack.
if (this->minimumOperatorStack.top()) { if (this->minimumOperatorStack.top()) {
storm::utility::reduceVectorMin(multiplyResult, newX, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMin(multiplyResult, *newX, nondeterministicChoiceIndices);
} else { } else {
storm::utility::reduceVectorMax(multiplyResult, newX, nondeterministicChoiceIndices);
storm::utility::vector::reduceVectorMax(multiplyResult, *newX, nondeterministicChoiceIndices);
} }
// Determine whether the method converged. // Determine whether the method converged.
converged = storm::utility::equalModuloPrecision(*currentX, *newX, precision, relative);
converged = storm::utility::vector::equalModuloPrecision(*currentX, *newX, precision, relative);
// Update environment variables. // Update environment variables.
swap = currentX; swap = currentX;

160
src/storm.cpp

@ -123,6 +123,7 @@ void printHeader(const int argc, const char* argv[]) {
std::cout << "-----" << std::endl << std::endl; std::cout << "-----" << std::endl << std::endl;
std::cout << "Version: 1.0 Alpha" << std::endl; std::cout << "Version: 1.0 Alpha" << std::endl;
// "Compute" the command line argument string with which STORM was invoked. // "Compute" the command line argument string with which STORM was invoked.
std::stringstream commandStream; std::stringstream commandStream;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
@ -132,14 +133,8 @@ void printHeader(const int argc, const char* argv[]) {
} }
/*! /*!
* Prints the footer.
*/
void printFooter() {
std::cout << "Nothing more to do, exiting." << std::endl;
}
/*!
* Function that parses the command line options.
* Parses the given command line arguments.
*
* @param argc The argc argument of main(). * @param argc The argc argument of main().
* @param argv The argv argument of main(). * @param argv The argv argument of main().
* @return True iff the program should continue to run after parsing the options. * @return True iff the program should continue to run after parsing the options.
@ -180,111 +175,77 @@ bool parseOptions(const int argc, const char* argv[]) {
return true; return true;
} }
/*!
* Performs some necessary initializations.
*/
void setUp() { void setUp() {
// Increase the precision of output.
std::cout.precision(10); std::cout.precision(10);
} }
/*! /*!
* Function to perform some cleanup.
* Performs some necessary clean-up.
*/ */
void cleanUp() { void cleanUp() {
delete storm::utility::cuddUtilityInstance(); delete storm::utility::cuddUtilityInstance();
} }
/*! /*!
* Factory style creation of new DTMC model checker
* @param dtmc The Dtmc that the model checker will check
* @return
* Creates a model checker for the given DTMC that complies with the given options.
*
* @param dtmc A reference to the DTMC for which the model checker is to be created.
* @return A pointer to the resulting model checker.
*/ */
storm::modelchecker::AbstractModelChecker<double>* createPrctlModelChecker(storm::models::Dtmc<double>& dtmc) {
storm::modelchecker::AbstractModelChecker<double>* createPrctlModelChecker(storm::models::Dtmc<double> const& dtmc) {
// Create the appropriate model checker.
storm::settings::Settings* s = storm::settings::instance(); storm::settings::Settings* s = storm::settings::instance();
if (s->getString("matrixlib") == "gmm++") { if (s->getString("matrixlib") == "gmm++") {
return new storm::modelchecker::GmmxxDtmcPrctlModelChecker<double>(dtmc); return new storm::modelchecker::GmmxxDtmcPrctlModelChecker<double>(dtmc);
} }
// The control flow should never reach this point, as there is a default setting for matrixlib (gmm++)
std::string message = "No matrix library suitable for DTMC model checking has been set";
// The control flow should never reach this point, as there is a default setting for matrixlib.
std::string message = "No matrix library suitable for DTMC model checking has been set.";
throw storm::exceptions::InvalidSettingsException() << message; throw storm::exceptions::InvalidSettingsException() << message;
return nullptr; return nullptr;
} }
/*! /*!
* Factory style creation of new MDP model checker
* Creates a model checker for the given MDP that complies with the given options.
*
* @param mdp The Dtmc that the model checker will check * @param mdp The Dtmc that the model checker will check
* @return * @return
*/ */
storm::modelchecker::AbstractModelChecker<double>* createPrctlModelChecker(storm::models::Mdp<double>& mdp) {
storm::modelchecker::AbstractModelChecker<double>* createPrctlModelChecker(storm::models::Mdp<double> const& mdp) {
// Create the appropriate model checker.
storm::settings::Settings* s = storm::settings::instance(); storm::settings::Settings* s = storm::settings::instance();
if (s->getString("matrixlib") == "gmm++") { if (s->getString("matrixlib") == "gmm++") {
return new storm::modelchecker::GmmxxMdpPrctlModelChecker<double>(mdp); return new storm::modelchecker::GmmxxMdpPrctlModelChecker<double>(mdp);
}
// The control flow should never reach this point, as there is a default setting for matrixlib (gmm++)
std::string message = "No matrix library suitable for MDP model checking has been set";
} else if (s->getString("matrixlib") == "native") {
return new storm::modelchecker::SparseMdpPrctlModelChecker<double>(mdp);
}
// The control flow should never reach this point, as there is a default setting for matrixlib.
std::string message = "No matrix library suitable for MDP model checking has been set.";
throw storm::exceptions::InvalidSettingsException() << message; throw storm::exceptions::InvalidSettingsException() << message;
return nullptr; return nullptr;
} }
/*! /*!
* Calls the check method of a model checker for all PRCTL formulas in a given list.
* Checks the PRCTL formulae provided on the command line on the given model checker.
* *
* @param formulaList The list of PRCTL formulas
* @param mc the model checker
*/
void checkPrctlFormulasAgainstModel(std::list<storm::property::prctl::AbstractPrctlFormula<double>*>& formulaList,
storm::modelchecker::AbstractModelChecker<double> const& mc) {
for ( auto formula : formulaList ) {
mc.check(*formula);
//TODO: Should that be done here or in a second iteration through the list?
delete formula;
}
formulaList.clear();
}
/*!
* Check method for DTMCs
* @param dtmc Reference to the DTMC to check
*/
void checkMdp(std::shared_ptr<storm::models::Mdp<double>> mdp) {
mdp->printModelInformationToStream(std::cout);
storm::settings::Settings* s = storm::settings::instance();
if (s->isSet("prctl")) {
LOG4CPLUS_INFO(logger, "Parsing prctl file"+ s->getString("prctl"));
storm::parser::PrctlFileParser fileParser;
std::list<storm::property::prctl::AbstractPrctlFormula<double>*> formulaList = fileParser.parseFormulas(s->getString("prctl"));
storm::modelchecker::AbstractModelChecker<double>* mc = createPrctlModelChecker(*mdp);
checkPrctlFormulasAgainstModel(formulaList, *mc);
delete mc;
}
if(s->isSet("csl")) {
LOG4CPLUS_ERROR(logger, "CSL properties cannot be checked on MDPs.");
}
}
/*!
* Check method for DTMCs
* @param dtmc Reference to the DTMC to check
* @param modelchecker The model checker that is to be invoked on all given formulae.
*/ */
void checkDtmc(std::shared_ptr<storm::models::Dtmc<double>> dtmc) {
dtmc->printModelInformationToStream(std::cout);
void checkPrctlFormulae(storm::modelchecker::AbstractModelChecker<double> const& modelchecker) {
storm::settings::Settings* s = storm::settings::instance(); storm::settings::Settings* s = storm::settings::instance();
if (s->isSet("prctl")) { if (s->isSet("prctl")) {
LOG4CPLUS_INFO(logger, "Parsing prctl file"+ s->getString("prctl"));
LOG4CPLUS_INFO(logger, "Parsing prctl file: " << s->getString("prctl") << ".");
storm::parser::PrctlFileParser fileParser; storm::parser::PrctlFileParser fileParser;
std::list<storm::property::prctl::AbstractPrctlFormula<double>*> formulaList = fileParser.parseFormulas(s->getString("prctl")); std::list<storm::property::prctl::AbstractPrctlFormula<double>*> formulaList = fileParser.parseFormulas(s->getString("prctl"));
storm::modelchecker::AbstractModelChecker<double>* mc = createPrctlModelChecker(*dtmc);
checkPrctlFormulasAgainstModel(formulaList, *mc);
delete mc;
}
if(s->isSet("csl")) {
LOG4CPLUS_ERROR(logger, "CSL properties cannot be checked on DTMCs.");
for (auto formula : formulaList) {
modelchecker.check(*formula);
delete formula;
}
} }
} }
@ -292,56 +253,66 @@ void checkDtmc(std::shared_ptr<storm::models::Dtmc<double>> dtmc) {
* Main entry point. * Main entry point.
*/ */
int main(const int argc, const char* argv[]) { int main(const int argc, const char* argv[]) {
// Catch segfaults and display a backtrace.
// Register a signal handler to catch segfaults and display a backtrace.
installSignalHandler(); installSignalHandler();
// Print an information header.
printHeader(argc, argv); printHeader(argc, argv);
// Initialize the logging engine and perform other initalizations.
initializeLogger(); initializeLogger();
setUp(); setUp();
try { try {
LOG4CPLUS_INFO(logger, "StoRM was invoked."); LOG4CPLUS_INFO(logger, "StoRM was invoked.");
// Parse options
// Parse options.
if (!parseOptions(argc, argv)) { if (!parseOptions(argc, argv)) {
// If false is returned, the program execution is stopped here
// E.g. if the user asked to see the help text
// If parsing failed or the option to see the usage was set, program execution stops here.
return 0; return 0;
} }
// Now, the settings are receivd and the model is parsed.
// Now, the settings are received and the specified model is parsed. The actual actions taken depend on whether
// the model was provided in explicit or symbolic format.
storm::settings::Settings* s = storm::settings::instance(); storm::settings::Settings* s = storm::settings::instance();
if (s->isSet("explicit")) { if (s->isSet("explicit")) {
std::vector<std::string> args = s->get<std::vector<std::string>>("explicit"); std::vector<std::string> args = s->get<std::vector<std::string>>("explicit");
storm::parser::AutoParser<double> parser(args[0], args[1], s->getString("staterew"), s->getString("transrew")); storm::parser::AutoParser<double> parser(args[0], args[1], s->getString("staterew"), s->getString("transrew"));
// Determine which engine is to be used to choose the right model checker.
LOG4CPLUS_DEBUG(logger, s->getString("matrixlib")); LOG4CPLUS_DEBUG(logger, s->getString("matrixlib"));
// Depending on the model type, the respective model checking procedure is chosen.
// Depending on the model type, the appropriate model checking procedure is chosen.
storm::modelchecker::AbstractModelChecker<double>* modelchecker = nullptr;
switch (parser.getType()) { switch (parser.getType()) {
case storm::models::DTMC: case storm::models::DTMC:
LOG4CPLUS_INFO(logger, "Model was detected as DTMC");
checkDtmc(parser.getModel<storm::models::Dtmc<double>>());
LOG4CPLUS_INFO(logger, "Model is a DTMC.");
modelchecker = createPrctlModelChecker(*parser.getModel<storm::models::Dtmc<double>>());
checkPrctlFormulae(*modelchecker);
break; break;
case storm::models::MDP: case storm::models::MDP:
LOG4CPLUS_INFO(logger, "Model was detected as MDP");
checkMdp(parser.getModel<storm::models::Mdp<double>>());
LOG4CPLUS_INFO(logger, "Model is an MDP.");
modelchecker = createPrctlModelChecker(*parser.getModel<storm::models::Mdp<double>>());
checkPrctlFormulae(*modelchecker);
break; break;
case storm::models::CTMC: case storm::models::CTMC:
LOG4CPLUS_INFO(logger, "Model is a CTMC.");
LOG4CPLUS_ERROR(logger, "The selected model type is not supported.");
break;
case storm::models::CTMDP: case storm::models::CTMDP:
// Continuous time model checking is not implemented yet
LOG4CPLUS_ERROR(logger, "The model type you selected is not supported in this version of storm.");
LOG4CPLUS_INFO(logger, "Model is a CTMC.");
LOG4CPLUS_ERROR(logger, "The selected model type is not supported.");
break; break;
case storm::models::Unknown: case storm::models::Unknown:
default: default:
LOG4CPLUS_ERROR(logger, "The model type could not be determined correctly."); LOG4CPLUS_ERROR(logger, "The model type could not be determined correctly.");
break; break;
} }
}
if (s->isSet("symbolic")) {
if (modelchecker != nullptr) {
delete modelchecker;
}
} else if (s->isSet("symbolic")) {
std::string arg = s->getString("symbolic"); std::string arg = s->getString("symbolic");
storm::parser::PrismParser parser; storm::parser::PrismParser parser;
storm::adapters::ExplicitModelAdapter adapter(parser.parseFile(arg)); storm::adapters::ExplicitModelAdapter adapter(parser.parseFile(arg));
@ -349,13 +320,12 @@ int main(const int argc, const char* argv[]) {
model->printModelInformationToStream(std::cout); model->printModelInformationToStream(std::cout);
} }
// Perform clean-up and terminate.
cleanUp(); cleanUp();
LOG4CPLUS_INFO(logger, "StoRM quit.");
LOG4CPLUS_INFO(logger, "StoRM terminating.");
return 0; return 0;
} catch (std::exception& e) { } catch (std::exception& e) {
LOG4CPLUS_FATAL(logger, "An exception was thrown but not catched. All we can do now is show it to you and die in peace...");
LOG4CPLUS_FATAL(logger, "An exception was thrown. Terminating.");
LOG4CPLUS_FATAL(logger, "\t" << e.what()); LOG4CPLUS_FATAL(logger, "\t" << e.what());
} }
return 1; return 1;

212
src/utility/Vector.h

@ -1,212 +0,0 @@
/*
* Vector.h
*
* Created on: 06.12.2012
* Author: Christian Dehnert
*/
#ifndef STORM_UTILITY_VECTOR_H_
#define STORM_UTILITY_VECTOR_H_
#include "Eigen/Core"
#include "ConstTemplates.h"
#include <iostream>
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
extern log4cplus::Logger logger;
namespace storm {
namespace utility {
template<class T>
void setVectorValues(std::vector<T>* vector, const storm::storage::BitVector& positions, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
(*vector)[position] = values[oldPosition++];
}
}
template<class T>
void setVectorValues(std::vector<T>* vector, const storm::storage::BitVector& positions, T value) {
for (auto position : positions) {
(*vector)[position] = value;
}
}
template<class T>
void setVectorValues(Eigen::Matrix<T, -1, 1, 0, -1, 1>* eigenVector, const storm::storage::BitVector& positions, T value) {
for (auto position : positions) {
(*eigenVector)(position, 0) = value;
}
}
template<class T>
void selectVectorValues(std::vector<T>* vector, const storm::storage::BitVector& positions, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
(*vector)[oldPosition++] = values[position];
}
}
template<class T>
void selectVectorValues(std::vector<T>* vector, const storm::storage::BitVector& positions, const std::vector<uint_fast64_t>& rowMapping, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
for (uint_fast64_t i = rowMapping[position]; i < rowMapping[position + 1]; ++i) {
(*vector)[oldPosition++] = values[i];
}
}
}
template<class T>
void selectVectorValuesRepeatedly(std::vector<T>* vector, const storm::storage::BitVector& positions, const std::vector<uint_fast64_t>& rowMapping, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
for (uint_fast64_t i = rowMapping[position]; i < rowMapping[position + 1]; ++i) {
(*vector)[oldPosition++] = values[position];
}
}
}
template<class T>
void subtractFromConstantOneVector(std::vector<T>* vector) {
for (auto it = vector->begin(); it != vector->end(); ++it) {
*it = storm::utility::constGetOne<T>() - *it;
}
}
template<class T>
void addVectors(std::vector<T>& target, std::vector<T> const& summand) {
if (target.size() != target.size()) {
LOG4CPLUS_ERROR(logger, "Lengths of vectors does not match and makes operation impossible.");
throw storm::exceptions::InvalidArgumentException() << "Length of vectors does not match and makes operation impossible.";
}
for (uint_fast64_t i = 0; i < target.size(); ++i) {
target[i] += summand[i];
}
}
template<class T>
void addVectors(std::vector<uint_fast64_t> const& states, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<T>& original, std::vector<T> const& summand) {
for (auto stateIt = states.cbegin(), stateIte = states.cend(); stateIt != stateIte; ++stateIt) {
for (auto rowIt = nondeterministicChoiceIndices[*stateIt], rowIte = nondeterministicChoiceIndices[*stateIt + 1]; rowIt != rowIte; ++rowIt) {
original[rowIt] += summand[rowIt];
}
}
}
template<class T>
void reduceVectorMin(std::vector<T> const& source, std::vector<T>* target, std::vector<uint_fast64_t> const& filter) {
uint_fast64_t currentSourceRow = 0;
uint_fast64_t currentTargetRow = -1;
for (auto it = source.cbegin(); it != source.cend(); ++it, ++currentSourceRow) {
// Check whether we have considered all source rows for the current target row.
if (filter[currentTargetRow + 1] <= currentSourceRow || currentSourceRow == 0) {
++currentTargetRow;
(*target)[currentTargetRow] = source[currentSourceRow];
continue;
}
// We have to minimize the value, so only overwrite the current value if the
// value is actually lower.
if (*it < (*target)[currentTargetRow]) {
(*target)[currentTargetRow] = *it;
}
}
}
template<class T>
void reduceVectorMin(std::vector<T> const& source, std::vector<T>* target, std::vector<uint_fast64_t> const& scc, std::vector<uint_fast64_t> const& filter) {
for (auto stateIt = scc.cbegin(); stateIt != scc.cend(); ++stateIt) {
(*target)[*stateIt] = source[filter[*stateIt]];
for (auto row = filter[*stateIt] + 1; row < filter[*stateIt + 1]; ++row) {
// We have to minimize the value, so only overwrite the current value if the
// value is actually lower.
if (source[row] < (*target)[*stateIt]) {
(*target)[*stateIt] = source[row];
}
}
}
}
template<class T>
void reduceVectorMax(std::vector<T> const& source, std::vector<T>* target, std::vector<uint_fast64_t> const& filter) {
uint_fast64_t currentSourceRow = 0;
uint_fast64_t currentTargetRow = -1;
for (auto it = source.cbegin(); it != source.cend(); ++it, ++currentSourceRow) {
// Check whether we have considered all source rows for the current target row.
if (filter[currentTargetRow + 1] <= currentSourceRow || currentSourceRow == 0) {
++currentTargetRow;
(*target)[currentTargetRow] = source[currentSourceRow];
continue;
}
// We have to maximize the value, so only overwrite the current value if the
// value is actually greater.
if (*it > (*target)[currentTargetRow]) {
(*target)[currentTargetRow] = *it;
}
}
}
template<class T>
void reduceVectorMax(std::vector<T> const& source, std::vector<T>* target, std::vector<uint_fast64_t> const& scc, std::vector<uint_fast64_t> const& filter) {
for (auto stateIt = scc.cbegin(); stateIt != scc.cend(); ++stateIt) {
(*target)[*stateIt] = source[filter[*stateIt]];
for (auto row = filter[*stateIt] + 1; row < filter[*stateIt + 1]; ++row) {
// We have to maximize the value, so only overwrite the current value if the
// value is actually lower.
if (source[row] > (*target)[*stateIt]) {
(*target)[*stateIt] = source[row];
}
}
}
}
template<class T>
bool equalModuloPrecision(std::vector<T> const& vectorLeft, std::vector<T> const& vectorRight, T precision, bool relativeError) {
if (vectorLeft.size() != vectorRight.size()) {
LOG4CPLUS_ERROR(logger, "Lengths of vectors does not match and makes comparison impossible.");
throw storm::exceptions::InvalidArgumentException() << "Length of vectors does not match and makes comparison impossible.";
}
for (uint_fast64_t i = 0; i < vectorLeft.size(); ++i) {
if (relativeError) {
if (std::abs(vectorLeft[i] - vectorRight[i])/vectorRight[i] > precision) return false;
} else {
if (std::abs(vectorLeft[i] - vectorRight[i]) > precision) return false;
}
}
return true;
}
template<class T>
bool equalModuloPrecision(std::vector<T> const& vectorLeft, std::vector<T> const& vectorRight, std::vector<uint_fast64_t> const& scc, T precision, bool relativeError) {
if (vectorLeft.size() != vectorRight.size()) {
LOG4CPLUS_ERROR(logger, "Lengths of vectors does not match and makes comparison impossible.");
throw storm::exceptions::InvalidArgumentException() << "Length of vectors does not match and makes comparison impossible.";
}
for (uint_fast64_t state : scc) {
if (relativeError) {
if (std::abs(vectorLeft[state] - vectorRight[state])/vectorRight[state] > precision) return false;
} else {
if (std::abs(vectorLeft[state] - vectorRight[state]) > precision) return false;
}
}
return true;
}
} //namespace utility
} //namespace storm
#endif /* STORM_UTILITY_VECTOR_H_ */

2
src/utility/graph.h

@ -1,5 +1,5 @@
/* /*
* GraphAnalyzer.h
* graph.h
* *
* Created on: 28.11.2012 * Created on: 28.11.2012
* Author: Christian Dehnert * Author: Christian Dehnert

281
src/utility/vector.h

@ -0,0 +1,281 @@
/*
* vector.h
*
* Created on: 06.12.2012
* Author: Christian Dehnert
*/
#ifndef STORM_UTILITY_VECTOR_H_
#define STORM_UTILITY_VECTOR_H_
#include "Eigen/Core"
#include "ConstTemplates.h"
#include <iostream>
#include <algorithm>
#include <functional>
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
extern log4cplus::Logger logger;
namespace storm {
namespace utility {
namespace vector {
/*!
* Sets the provided values at the provided positions in the given vector.
*
* @param vector The vector in which the values are to be set.
* @param positions The positions at which the values are to be set.
* @param values The values that are to be set.
*/
template<class T>
void setVectorValues(std::vector<T>& vector, storm::storage::BitVector const& positions, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
vector[position] = values[oldPosition++];
}
}
/*!
* Sets the provided value at the provided positions in the given vector.
*
* @param vector The vector in which the value is to be set.
* @param positions The positions at which the value is to be set.
* @param value The value that is to be set.
*/
template<class T>
void setVectorValues(std::vector<T>& vector, storm::storage::BitVector const& positions, T value) {
for (auto position : positions) {
vector[position] = value;
}
}
/*!
* Sets the provided value at the provided positions in the given vector.
*
* @param vector The vector in which the value is to be set.
* @param positions The positions at which the value is to be set.
* @param value The value that is to be set.
*/
template<class T>
void setVectorValues(Eigen::Matrix<T, -1, 1, 0, -1, 1>& eigenVector, storm::storage::BitVector const& positions, T value) {
for (auto position : positions) {
eigenVector(position, 0) = value;
}
}
/*!
* Selects the elements from a vector at the specified positions and writes them consecutively into another vector.
* @param vector The vector into which the selected elements are to be written.
* @param positions The positions at which to select the elements from the values vector.
* @param values The vector from which to select the elements.
*/
template<class T>
void selectVectorValues(std::vector<T>& vector, storm::storage::BitVector const& positions, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
vector[oldPosition++] = values[position];
}
}
/*!
* Selects groups of elements from a vector at the specified positions and writes them consecutively into another vector.
*
* @param vector The vector into which the selected elements are to be written.
* @param positions The positions of the groups of elements that are to be selected.
* @param rowGrouping A vector that specifies the begin and end of each group of elements in the values vector.
* @param values The vector from which to select groups of elements.
*/
template<class T>
void selectVectorValues(std::vector<T>& vector, storm::storage::BitVector const& positions, std::vector<uint_fast64_t> const& rowGrouping, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
for (uint_fast64_t i = rowGrouping[position]; i < rowGrouping[position + 1]; ++i) {
vector[oldPosition++] = values[i];
}
}
}
/*!
* Selects values from a vector at the specified positions and writes them into another vector as often as given by
* the size of the corresponding group of elements.
*
* @param vector The vector into which the selected elements are written.
* @param positions The positions at which to select the values.
* @param rowGrouping A vector that specifies the begin and end of each group of elements in the values vector. This
* implicitly defines the number of times any element is written to the output vector.
*/
template<class T>
void selectVectorValuesRepeatedly(std::vector<T>& vector, storm::storage::BitVector const& positions, std::vector<uint_fast64_t> const& rowGrouping, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (auto position : positions) {
for (uint_fast64_t i = rowGrouping[position]; i < rowGrouping[position + 1]; ++i) {
vector[oldPosition++] = values[position];
}
}
}
/*!
* Subtracts the given vector from the constant one-vector and writes the result to the input vector.
*
* @param vector The vector that is to be subtracted from the constant one-vector.
*/
template<class T>
void subtractFromConstantOneVector(std::vector<T>& vector) {
for (auto element : vector) {
element = storm::utility::constGetOne<T>() - element;
}
}
/*!
* Adds the two given vectors and writes the result into the first operand.
*
* @param target The first summand and target vector.
* @param summand The second summand.
*/
template<class T>
void addVectorsInPlace(std::vector<T>& target, std::vector<T> const& summand) {
if (target.size() != summand.size()) {
LOG4CPLUS_ERROR(logger, "Lengths of vectors do not match, which makes operation impossible.");
throw storm::exceptions::InvalidArgumentException() << "Length of vectors do not match, which makes operation impossible.";
}
std::transform(target.begin(), target.end(), summand.begin(), target.begin(), std::plus<T>());
}
/*!
* Reduces the given source vector by selecting an element according to the given filter out of each row group.
*
* @param source The source vector which is to be reduced.
* @param target The target vector into which a single element from each row group is written.
* @param rowGrouping A vector that specifies the begin and end of each group of elements in the values vector.
* @param filter A function that compares two elements v1 and v2 according to some filter criterion. This function must
* return true iff v1 is supposed to be taken instead of v2.
*/
template<class T>
void reduceVector(std::vector<T> const& source, std::vector<T>& target, std::vector<uint_fast64_t> const& rowGrouping, std::function<bool (T const&, T const&)> filter) {
uint_fast64_t currentSourceRow = 0;
uint_fast64_t currentTargetRow = -1;
for (auto it = source.cbegin(), ite = source.cend(); it != ite; ++it, ++currentSourceRow) {
// Check whether we have considered all source rows for the current target row.
if (rowGrouping[currentTargetRow + 1] <= currentSourceRow || currentSourceRow == 0) {
++currentTargetRow;
target[currentTargetRow] = source[currentSourceRow];
continue;
}
// We have to minimize the value, so only overwrite the current value if the
// value is actually lower.
if (filter(*it, target[currentTargetRow])) {
target[currentTargetRow] = *it;
}
}
}
/*!
* Reduces the given source vector by selecting the smallest element out of each row group.
*
* @param source The source vector which is to be reduced.
* @param target The target vector into which a single element from each row group is written.
* @param rowGrouping A vector that specifies the begin and end of each group of elements in the values vector.
*/
template<class T>
void reduceVectorMin(std::vector<T> const& source, std::vector<T>& target, std::vector<uint_fast64_t> const& rowGrouping) {
reduceVector<T>(source, target, rowGrouping, [] (T const& val1, T const& val2) -> bool { return val1 < val2; });
}
/*!
* Reduces the given source vector by selecting the largest element out of each row group.
*
* @param source The source vector which is to be reduced.
* @param target The target vector into which a single element from each row group is written.
* @param rowGrouping A vector that specifies the begin and end of each group of elements in the values vector.
*/
template<class T>
void reduceVectorMax(std::vector<T> const& source, std::vector<T>& target, std::vector<uint_fast64_t> const& rowGrouping) {
reduceVector<T>(source, target, rowGrouping, [] (T const& val1, T const& val2) -> bool { return val1 > val2; });
}
/*!
* Compares the given elements and determines whether they are equal modulo the given precision. The provided flag
* additionaly specifies whether the error is computed in relative or absolute terms.
*
* @param val1 The first value to compare.
* @param val2 The second value to compare.
* @param precision The precision up to which the elements are compared.
* @param relativeError If set, the error is computed relative to the second value.
* @return True iff the elements are considered equal.
*/
template<class T>
bool equalModuloPrecision(T const& val1, T const& val2, T precision, bool relativeError = true) {
if (relativeError) {
if (std::abs(val1 - val2)/val2 > precision) return false;
} else {
if (std::abs(val1 - val2) > precision) return false;
}
return true;
}
/*!
* Compares the two vectors and determines whether they are equal modulo the provided precision. Depending on whether the
* flag is set, the difference between the vectors is computed relative to the value or in absolute terms.
*
* @param vectorLeft The first vector of the comparison.
* @param vectorRight The second vector of the comparison.
* @param precision The precision up to which the vectors are to be checked for equality.
* @param relativeError If set, the difference between the vectors is computed relative to the value or in absolute terms.
*/
template<class T>
bool equalModuloPrecision(std::vector<T> const& vectorLeft, std::vector<T> const& vectorRight, T precision, bool relativeError) {
if (vectorLeft.size() != vectorRight.size()) {
LOG4CPLUS_ERROR(logger, "Lengths of vectors do not match, which makes comparison impossible.");
throw storm::exceptions::InvalidArgumentException() << "Lengths of vectors do not match, which makes comparison impossible.";
}
for (uint_fast64_t i = 0; i < vectorLeft.size(); ++i) {
if (!equalModuloPrecision(vectorLeft[i], vectorRight[i], precision, relativeError)) {
return false;
}
}
return true;
}
/*!
* Compares the two vectors at the specified positions and determines whether they are equal modulo the provided
* precision. Depending on whether the flag is set, the difference between the vectors is computed relative to the value
* or in absolute terms.
*
* @param vectorLeft The first vector of the comparison.
* @param vectorRight The second vector of the comparison.
* @param precision The precision up to which the vectors are to be checked for equality.
* @param positions A vector representing a set of positions at which the vectors are compared.
* @param relativeError If set, the difference between the vectors is computed relative to the value or in absolute terms.
*/
template<class T>
bool equalModuloPrecision(std::vector<T> const& vectorLeft, std::vector<T> const& vectorRight, std::vector<uint_fast64_t> const& positions, T precision, bool relativeError) {
if (vectorLeft.size() != vectorRight.size()) {
LOG4CPLUS_ERROR(logger, "Lengths of vectors do not match, which makes comparison impossible.");
throw storm::exceptions::InvalidArgumentException() << "Lengths of vectors do not match, which makes comparison impossible.";
}
for (uint_fast64_t position : positions) {
if (!equalModuloPrecision(vectorLeft[position], vectorRight[position], precision, relativeError)) {
return false;
}
}
return true;
}
} // namespace vector
} // namespace utility
} // namespace storm
#endif /* STORM_UTILITY_VECTOR_H_ */
Loading…
Cancel
Save