Browse Source

Merge branch 'master' of https://sselab.de/lab9/private/git/MRMC

tempestpy_adaptions
PBerger 12 years ago
parent
commit
50d9ce22de
  1. 41
      src/exceptions/BaseException.h
  2. 29
      src/exceptions/InvalidSettings.h
  3. 8
      src/modelChecker/DtmcPrctlModelChecker.h
  4. 1
      src/modelChecker/EigenDtmcPrctlModelChecker.h
  5. 139
      src/modelChecker/GmmxxDtmcPrctlModelChecker.h
  6. 19
      src/mrmc.cpp
  7. 27
      src/parser/readPrctlFile.cpp
  8. 27
      src/utility/settings.cpp
  9. 8
      src/utility/settings.h

41
src/exceptions/BaseException.h

@ -0,0 +1,41 @@
#ifndef BASEEXCEPTION_H_
#define BASEEXCEPTION_H_
#include <exception>
#include <sstream>
namespace mrmc {
namespace exceptions {
template<typename E>
class BaseException : public std::exception
{
public:
BaseException() : exception() {}
BaseException(const BaseException& cp)
: exception(cp), stream(cp.stream.str())
{
}
~BaseException() throw() { }
template<class T>
E& operator<<(const T& var)
{
this->stream << var;
return * dynamic_cast<E*>(this);
}
virtual const char* what() const throw()
{
return this->stream.str().c_str();
}
private:
std::stringstream stream;
};
} // namespace exceptions
} // namespace mrmc
#endif // BASEEXCEPTION_H_

29
src/exceptions/InvalidSettings.h

@ -1,35 +1,16 @@
#ifndef MRMC_EXCEPTIONS_INVALID_SETTINGS_H_
#define MRMC_EXCEPTIONS_INVALID_SETTINGS_H_
#ifndef INVALIDSETTINGS_H_
#define INVALIDSETTINGS_H_
#include <exception>
#include "src/exceptions/BaseException.h"
namespace mrmc {
namespace exceptions {
//!This exception is thrown when a memory request can't be
//!fulfilled.
class InvalidSettings : public std::exception
class InvalidSettings : public BaseException<InvalidSettings>
{
public:
/* The Visual C++-Version of the exception class has constructors accepting
* a char*-constant; The GCC version does not have these
*
* As the "extended" constructor is used in the sparse matrix code, a dummy
* constructor is used under linux (which will ignore the parameter)
*/
#ifdef _WIN32
InvalidSettings() : exception("::mrmc::InvalidSettings"){}
InvalidSettings(const char * const s): exception(s) {}
#else
InvalidSettings() : exception() {}
InvalidSettings(const char * const s): exception() {}
#endif
virtual const char* what() const throw()
{ return "mrmc::InvalidSettings"; }
};
} // namespace exceptions
} // namespace mrmc
#endif // MRMC_EXCEPTIONS_INVALID_SETTINGS_H_
#endif // INVALIDSETTINGS_H_

8
src/modelChecker/DtmcPrctlModelChecker.h

@ -186,17 +186,23 @@ public:
*/
mrmc::storage::BitVector* checkProbabilisticIntervalOperator(
const mrmc::formula::ProbabilisticIntervalOperator<Type>& formula) const {
// First, we need to compute the probability for satisfying the path formula for each state.
std::vector<Type>* probabilisticResult = this->checkPathFormula(formula.getPathFormula());
// Create resulting bit vector, which will hold the yes/no-answer for every state.
mrmc::storage::BitVector* result = new mrmc::storage::BitVector(this->getModel().getNumberOfStates());
// Now, we can compute which states meet the bound specified in this operator, i.e.
// lie in the interval that was given along with this operator, and set the corresponding bits
// to true in the resulting vector.
Type lower = formula.getLowerBound();
Type upper = formula.getUpperBound();
for (uint_fast64_t i = 0; i < this->getModel().getNumberOfStates(); ++i) {
if ((*probabilisticResult)[i] >= lower && (*probabilisticResult)[i] <= upper) result->set(i, true);
}
// Delete the probabilities computed for the states and return result.
delete probabilisticResult;
return result;
}

1
src/modelChecker/EigenDtmcPrctlModelChecker.h

@ -157,6 +157,7 @@ public:
// Transform the submatric matrix to the eigen format to use its solvers
Eigen::SparseMatrix<Type, 1, int_fast32_t>* eigenSubMatrix = submatrix->toEigenSparseMatrix();
delete submatrix;
// Initialize the x vector with 0.5 for each element. This is the initial guess for
// the iterative solvers. It should be safe as for all 'maybe' states we know that the

139
src/modelChecker/GmmxxDtmcPrctlModelChecker.h

@ -8,11 +8,14 @@
#ifndef GMMXXDTMCPRCTLMODELCHECKER_H_
#define GMMXXDTMCPRCTLMODELCHECKER_H_
#include "src/utility/vector.h"
#include <cmath>
#include "src/models/Dtmc.h"
#include "src/modelChecker/DtmcPrctlModelChecker.h"
#include "src/solver/GraphAnalyzer.h"
#include "src/utility/vector.h"
#include "src/utility/settings.h"
#include "gmm/gmm_matrix.h"
#include "gmm/gmm_iter_solvers.h"
@ -46,24 +49,23 @@ public:
mrmc::storage::SquareSparseMatrix<Type> tmpMatrix(*this->getModel().getTransitionProbabilityMatrix());
// Make all rows absorbing that violate both sub-formulas or satisfy the second sub-formula.
tmpMatrix.makeRowsAbsorbing((~*leftStates & *rightStates) | *rightStates);
tmpMatrix.makeRowsAbsorbing(~(*leftStates & *rightStates) | *rightStates);
// Transform the transition probability matrix to the gmm++ format to use its arithmetic.
gmm::csr_matrix<double>* gmmxxMatrix = tmpMatrix.toGMMXXSparseMatrix();
gmm::csr_matrix<Type>* gmmxxMatrix = tmpMatrix.toGMMXXSparseMatrix();
// Create the vector with which to multiply.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
mrmc::utility::setVectorValues(result, *rightStates, static_cast<double>(1.0));
mrmc::utility::setVectorValues(result, *rightStates, static_cast<Type>(1.0));
// Now perform matrix-vector multiplication as long as we meet the bound of the formula.
for (uint_fast64_t i = 0; i < formula.getBound(); ++i) {
gmm::mult(*gmmxxMatrix, *result, *result);
}
// Delete intermediate results.
// Delete intermediate results and return result.
delete leftStates;
delete rightStates;
return result;
}
@ -72,19 +74,19 @@ public:
mrmc::storage::BitVector* nextStates = this->checkStateFormula(formula.getChild());
// Transform the transition probability matrix to the gmm++ format to use its arithmetic.
gmm::csr_matrix<double>* gmmxxMatrix = this->getModel().getTransitionProbabilityMatrix()->toGMMXXSparseMatrix();
gmm::csr_matrix<Type>* gmmxxMatrix = this->getModel().getTransitionProbabilityMatrix()->toGMMXXSparseMatrix();
// Create the vector with which to multiply and initialize it correctly.
std::vector<Type> x(this->getModel().getNumberOfStates());
mrmc::utility::setVectorValues(&x, *nextStates, static_cast<double>(1.0));
mrmc::utility::setVectorValues(&x, *nextStates, static_cast<Type>(1.0));
// Delete not needed next states bit vector.
// Delete obsolete sub-result.
delete nextStates;
// Create resulting vector.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
// Perform the actual computation.
// Perform the actual computation, namely matrix-vector multiplication.
gmm::mult(*gmmxxMatrix, x, *result);
// Delete temporary matrix and return result.
@ -101,9 +103,10 @@ public:
// all states that have probability 0 and 1 of satisfying the until-formula.
mrmc::storage::BitVector notExistsPhiUntilPsiStates(this->getModel().getNumberOfStates());
mrmc::storage::BitVector alwaysPhiUntilPsiStates(this->getModel().getNumberOfStates());
mrmc::solver::GraphAnalyzer::getPhiUntilPsiStates<double>(this->getModel(), *leftStates, *rightStates, &notExistsPhiUntilPsiStates, &alwaysPhiUntilPsiStates);
mrmc::solver::GraphAnalyzer::getPhiUntilPsiStates(this->getModel(), *leftStates, *rightStates, &notExistsPhiUntilPsiStates, &alwaysPhiUntilPsiStates);
notExistsPhiUntilPsiStates.complement();
// Delete sub-results that are obsolete now.
delete leftStates;
delete rightStates;
@ -118,13 +121,14 @@ public:
// Only try to solve system if there are states for which the probability is unknown.
if (maybeStates.getNumberOfSetBits() > 0) {
// Now we can eliminate the rows and columns from the original transition probability matrix.
mrmc::storage::SquareSparseMatrix<double>* submatrix = this->getModel().getTransitionProbabilityMatrix()->getSubmatrix(maybeStates);
// Converting the matrix to the form needed for the equation system. That is, we go from
// x = A*x + b to (I-A)x = b.
mrmc::storage::SquareSparseMatrix<Type>* submatrix = this->getModel().getTransitionProbabilityMatrix()->getSubmatrix(maybeStates);
// Converting the matrix from the fixpoint notation to the form needed for the equation
// system. That is, we go from x = A*x + b to (I-A)x = b.
submatrix->convertToEquationSystem();
// Transform the submatrix to the gmm++ format to use its solvers.
gmm::csr_matrix<double>* gmmxxMatrix = submatrix->toGMMXXSparseMatrix();
gmm::csr_matrix<Type>* gmmxxMatrix = submatrix->toGMMXXSparseMatrix();
delete submatrix;
// Initialize the x vector with 0.5 for each element. This is the initial guess for
// the iterative solvers. It should be safe as for all 'maybe' states we know that the
@ -133,19 +137,58 @@ public:
// 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<double> b(maybeStates.getNumberOfSetBits());
this->getModel().getTransitionProbabilityMatrix()->getConstrainedRowCountVector(maybeStates, alwaysPhiUntilPsiStates, &x);
std::vector<Type> b(maybeStates.getNumberOfSetBits());
this->getModel().getTransitionProbabilityMatrix()->getConstrainedRowCountVector(maybeStates, alwaysPhiUntilPsiStates, &b);
// Get the settings object to customize linear solving.
mrmc::settings::Settings* s = mrmc::settings::instance();
// Set up the precondition of the iterative solver.
gmm::ilu_precond<gmm::csr_matrix<double>> P(*gmmxxMatrix);
// Prepare an iteration object that determines the accuracy, maximum number of iterations
// and the like.
gmm::iteration iter(0.000001);
gmm::iteration iter(s->get<double>("precision"), 0, s->get<unsigned>("lemaxiter"));
// Now do the actual solving.
LOG4CPLUS_INFO(logger, "Starting iterative solver.");
gmm::bicgstab(*gmmxxMatrix, x, b, P, iter);
LOG4CPLUS_INFO(logger, "Iterative solver converged.");
const std::string& precond = s->getString("precond");
if (s->getString("lemethod").compare("bicgstab") == 0) {
if (precond.compare("ilu")) {
gmm::bicgstab(*gmmxxMatrix, x, b, gmm::ilu_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), iter);
} else if (precond.compare("diagonal") == 0) {
gmm::bicgstab(*gmmxxMatrix, x, b, gmm::diagonal_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), iter);
} else if (precond.compare("ildlt") == 0) {
gmm::bicgstab(*gmmxxMatrix, x, b, gmm::ildlt_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), iter);
} else if (precond.compare("none") == 0) {
gmm::bicgstab(*gmmxxMatrix, x, b, gmm::identity_matrix(), iter);
}
// FIXME: gmres has been disabled, because it triggers gmm++ compilation errors
/* } else if (s->getString("lemethod").compare("gmres") == 0) {
if (precond.compare("ilu")) {
gmm::gmres(*gmmxxMatrix, x, b, gmm::ilu_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), s->get<unsigned>("restart"), iter);
} else if (precond.compare("diagonal") == 0) {
gmm::gmres(*gmmxxMatrix, x, b, gmm::diagonal_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), s->get<unsigned>("restart"), iter);
} else if (precond.compare("ildlt") == 0) {
gmm::gmres(*gmmxxMatrix, x, b, gmm::ildlt_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), s->get<unsigned>("restart"), iter);
} else if (precond.compare("none") == 0) {
gmm::gmres(*gmmxxMatrix, x, b, gmm::identity_matrix(), s->get<unsigned>("restart"), iter);
} */
} else if (s->getString("lemethod").compare("qmr") == 0) {
if (precond.compare("ilu")) {
gmm::qmr(*gmmxxMatrix, x, b, gmm::ilu_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), iter);
} else if (precond.compare("diagonal") == 0) {
gmm::qmr(*gmmxxMatrix, x, b, gmm::diagonal_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), iter);
} else if (precond.compare("ildlt") == 0) {
gmm::qmr(*gmmxxMatrix, x, b, gmm::ildlt_precond<gmm::csr_matrix<Type>>(*gmmxxMatrix), iter);
} else if (precond.compare("none") == 0) {
gmm::qmr(*gmmxxMatrix, x, b, gmm::identity_matrix(), iter);
}
}
// Check if the solver converged and issue a warning otherwise.
if (iter.converged()) {
LOG4CPLUS_INFO(logger, "Iterative solver converged after " << iter.get_iteration() << " iterations.");
} else {
LOG4CPLUS_WARN(logger, "Iterative solver did not converge.");
}
// Set values of resulting vector according to result.
mrmc::utility::setVectorValues<Type>(result, maybeStates, x);
@ -154,11 +197,59 @@ public:
delete gmmxxMatrix;
}
mrmc::utility::setVectorValues<Type>(result, notExistsPhiUntilPsiStates, static_cast<double>(0));
mrmc::utility::setVectorValues<Type>(result, alwaysPhiUntilPsiStates, static_cast<double>(1.0));
// Set values of resulting vector that are known exactly.
mrmc::utility::setVectorValues<Type>(result, notExistsPhiUntilPsiStates, static_cast<Type>(0));
mrmc::utility::setVectorValues<Type>(result, alwaysPhiUntilPsiStates, static_cast<Type>(1.0));
return result;
}
/*!
* Returns the name of this module.
* @return The name of this module.
*/
static std::string getModuleName() {
return "gmm++";
}
/*!
* Returns a trigger such that if the option "matrixlib" is set to "gmm++", this model checker
* is to be used.
* @return An option trigger for this module.
*/
static std::pair<std::string, std::string> getOptionTrigger() {
return std::pair<std::string, std::string>("matrixlib", "gmm++");
}
/*!
* Registers all options associated with the gmm++ matrix library.
*/
static void putOptions(boost::program_options::options_description* desc) {
desc->add_options()("lemethod", boost::program_options::value<std::string>()->default_value("bicgstab")->notifier(&validateLeMethod), "Sets the method used for linear equation solving. Must be in {bicgstab, qmr}.");
desc->add_options()("lemaxiter", boost::program_options::value<unsigned>()->default_value(10000), "Sets the maximal number of iterations for iterative linear equation solving.");
desc->add_options()("precision", boost::program_options::value<double>()->default_value(10e-6), "Sets the precision for iterative linear equation solving.");
desc->add_options()("precond", boost::program_options::value<std::string>()->default_value("ilu")->notifier(&validatePreconditioner), "Sets the preconditioning technique for linear equation solving. Must be in {ilu, diagonal, ildlt, none}.");
}
/*!
* Validates whether the given lemethod matches one of the available ones.
* Throws an exception of type InvalidSettings in case the selected method is illegal.
*/
static void validateLeMethod(const std::string& lemethod) {
if (lemethod.compare("bicgstab") != 0 && lemethod.compare("qmr") != 0) {
throw exceptions::InvalidSettings() << "Argument " << lemethod << " for option 'lemethod' is invalid.";
}
}
/*!
* Validates whether the given preconditioner matches one of the available ones.
* Throws an exception of type InvalidSettings in case the selected preconditioner is illegal.
*/
static void validatePreconditioner(const std::string& preconditioner) {
if (preconditioner.compare("ilu") != 0 && preconditioner.compare("diagonal") != 0 && preconditioner.compare("ildlt") && preconditioner.compare("none") != 0) {
throw exceptions::InvalidSettings() << "Argument " << preconditioner << " for option 'precond' is invalid.";
}
}
};
} //namespace modelChecker

19
src/mrmc.cpp

@ -62,7 +62,7 @@ void setUpConsoleLogging() {
int main(const int argc, const char* argv[]) {
setUpFileLogging();
mrmc::settings::Settings* s = NULL;
mrmc::settings::Settings* s = nullptr;
LOG4CPLUS_INFO(logger, "This is the Markov Reward Model Checker (MRMC) by i2 of RWTH Aachen University.");
@ -74,9 +74,12 @@ int main(const int argc, const char* argv[]) {
LOG4CPLUS_INFO(logger, "MRMC command invoked " << commandStream.str());
try {
mrmc::settings::Settings::registerModule<mrmc::modelChecker::GmmxxDtmcPrctlModelChecker<double> >();
s = mrmc::settings::newInstance(argc, argv, nullptr);
} catch (mrmc::exceptions::InvalidSettings&) {
} catch (mrmc::exceptions::InvalidSettings e) {
LOG4CPLUS_FATAL(logger, "InvalidSettings error: " << e.what());
LOG4CPLUS_FATAL(logger, "Could not recover from settings error, terminating.");
std::cout << "Could not recover from settings error: " << e.what() << std::endl;
std::cout << std::endl << mrmc::settings::help;
delete s;
return 1;
@ -106,14 +109,16 @@ int main(const int argc, const char* argv[]) {
dtmc.printModelInformationToStream(std::cout);
// Uncomment this if you want to see the first model checking procedure in action. :)
mrmc::modelChecker::EigenDtmcPrctlModelChecker<double> mc(dtmc);
mrmc::formula::AP<double>* trueFormula = new mrmc::formula::AP<double>(std::string("true"));
mrmc::formula::AP<double>* ap = new mrmc::formula::AP<double>(std::string("observe0Greater1"));
mrmc::formula::Until<double>* until = new mrmc::formula::Until<double>(trueFormula, ap);
std::vector<double>* eigenResult = NULL;
try {
eigenResult = mc.checkPathFormula(*until);
std::vector<double>* eigenResult = mc.checkPathFormula(*until);
delete eigenResult;
} catch (mrmc::exceptions::NoConvergence& nce) {
// solver did not converge
LOG4CPLUS_ERROR(logger, "EigenDtmcPrctlModelChecker did not converge with " << nce.getIterationCount() << " of max. " << nce.getMaxIterationCount() << "Iterations!");
@ -121,13 +126,16 @@ int main(const int argc, const char* argv[]) {
}
delete until;
mrmc::modelChecker::GmmxxDtmcPrctlModelChecker<double> mcG(dtmc);
mrmc::formula::AP<double>* trueFormulaG = new mrmc::formula::AP<double>(std::string("true"));
mrmc::formula::AP<double>* apG = new mrmc::formula::AP<double>(std::string("observe0Greater1"));
mrmc::formula::Until<double>* untilG = new mrmc::formula::Until<double>(trueFormulaG, apG);
std::vector<double>* gmmResult = mcG.checkPathFormula(*untilG);
std::vector<double>* vec = mcG.checkPathFormula(*untilG);
delete vec;
delete untilG;
/*
if (eigenResult->size() != gmmResult->size()) {
LOG4CPLUS_ERROR(logger, "Warning: Eigen and GMM produced different results (Eigen: " << eigenResult->size() << ", Gmm: " << gmmResult->size() << ") in size!");
} else {
@ -141,6 +149,7 @@ int main(const int argc, const char* argv[]) {
}
}
}
*/
/*
LOG4CPLUS_INFO(logger, "Result: ");

27
src/parser/readPrctlFile.cpp

@ -89,6 +89,33 @@ namespace
ws = *( space );
value %= ( double_ | int_ ); // double_ must be *before* int_
type = string("int") | string("double");
/*
* Todo:
* Use two arguments at one point in the code, e.g. do something like
* this->variables[ variable ] = value
*
* You can have local variables in rules, but somehow does not work.
* You can also (somehow) let a rule return some arbitrary class and let boost magically collect the arguments for the constructor.
* No idea how this can possibly work, did not get this to work.
* You can also generate a syntax tree and do this manually (-> utree)... somehow.
*
* Attention: spirit had some major upgrades in the last few releases. 1.48 already lacks some features that might be useful.
*
* The rules parse the const definitions of
* http://www.prismmodelchecker.org/manual/PropertySpecification/PropertiesFiles
* We actually do not need them, but the problems I described above are fairly generic.
* We will not be able to parse the formulas if we don't solve them...
*
* Example input:
* const int k = 7;
* const double T = 9;
* const double p = 0.01;
*
* Parser can be run via ./mrmc --test-prctl <filename> foo bar
* foo and bar are necessary, otherwise the option parser fails...
*/
varDef =
string("const") >> ws >>
type >> ws >>

27
src/utility/settings.cpp

@ -7,6 +7,8 @@
#include "src/utility/settings.h"
#include "src/exceptions/BaseException.h"
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
extern log4cplus::Logger logger;
@ -25,7 +27,7 @@ std::unique_ptr<bpo::options_description> mrmc::settings::Settings::desc = nullp
std::string mrmc::settings::Settings::binaryName = "";
mrmc::settings::Settings* mrmc::settings::Settings::inst = nullptr;
std::map< std::pair<std::string, std::string>, bpo::options_description* > mrmc::settings::Settings::modules;
std::map< std::pair<std::string, std::string>, std::shared_ptr<bpo::options_description> > mrmc::settings::Settings::modules;
/*!
* The constructor fills the option descriptions, parses the
@ -72,6 +74,8 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
// Perform first parse run
this->firstRun(argc, argv, filename);
// Buffer for items to be deleted
std::list< std::pair< std::string, std::string > > deleteQueue;
// Check module triggers
for (auto it : Settings::modules)
{
@ -81,11 +85,12 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
if (this->vm[trigger.first].as<std::string>().compare(trigger.second) == 0)
{
Settings::desc->add(*it.second);
Settings::modules.erase(trigger);
deleteQueue.push_back(trigger);
}
}
}
for (auto it : deleteQueue) Settings::modules.erase(it);
// Stop if help is set
if (this->vm.count("help") > 0)
@ -107,27 +112,19 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
}
catch (bpo::required_option e)
{
std::cerr << "Required option: " << e.what() << std::endl;
LOG4CPLUS_ERROR(logger, "Required option: " << e.what());
throw mrmc::exceptions::InvalidSettings();
throw mrmc::exceptions::InvalidSettings() << "Required option missing";
}
catch (bpo::validation_error e)
{
std::cerr << "Validation failed: " << e.what() << std::endl;
LOG4CPLUS_ERROR(logger, "Validation failed: " << e.what());
throw mrmc::exceptions::InvalidSettings();
throw mrmc::exceptions::InvalidSettings() << "Validation failed: " << e.what();
}
catch (bpo::invalid_command_line_syntax e)
{
std::cerr << "Invalid command line syntax: " << e.what() << std::endl;
LOG4CPLUS_ERROR(logger, "Invalid command line syntax: " << e.what());
throw mrmc::exceptions::InvalidSettings();
throw mrmc::exceptions::InvalidSettings() << e.what();
}
catch (bpo::error e)
{
std::cerr << e.what() << std::endl;
LOG4CPLUS_ERROR(logger, "Unknown error: " << e.what());
throw mrmc::exceptions::InvalidSettings();
throw mrmc::exceptions::InvalidSettings() << e.what();
}
}

8
src/utility/settings.h

@ -52,7 +52,7 @@ namespace settings {
*/
template <typename T>
const T& get(const std::string &name) const {
if (this->vm.count(name) == 0) throw mrmc::exceptions::InvalidSettings();
if (this->vm.count(name) == 0) throw mrmc::exceptions::InvalidSettings() << "Could not read option " << name << ".";
return this->vm[name].as<T>();
}
@ -113,9 +113,9 @@ namespace settings {
// build description name
std::stringstream str;
str << T::getModuleName() << " (" << trigger.first << " = " << trigger.second << ")";
bpo::options_description* desc = new bpo::options_description(str.str());
std::shared_ptr<bpo::options_description> desc = std::shared_ptr<bpo::options_description>(new bpo::options_description(str.str()));
// but options
T::putOptions(desc);
T::putOptions(desc.get());
// store
Settings::modules[ trigger ] = desc;
}
@ -159,7 +159,7 @@ namespace settings {
/*!
* @brief Contains option descriptions for all modules.
*/
static std::map< std::pair< std::string, std::string >, bpo::options_description* > modules;
static std::map< std::pair< std::string, std::string >, std::shared_ptr<bpo::options_description> > modules;
/*!
* @brief option mapping.

Loading…
Cancel
Save