STORM_LOG_THROW(false,storm::exceptions::NotSupportedException,"No exact numbers are supported in this build.");
STORM_LOG_THROW(mpi.verificationValueType==ModelProcessingInformation::ValueType::FinitePrecision,storm::exceptions::NotSupportedException,"No exact numbers or parameters are supported in this build.");
STORM_LOG_THROW(input.model.is_initialized(),storm::exceptions::InvalidArgumentException,"Portfolio engine requires a symbolic model (PRISM or JANI.");
STORM_LOG_THROW(!properties.empty(),storm::exceptions::InvalidArgumentException,"Portfolio engine requires a property.");
STORM_LOG_WARN_COND(properties.size()==1,"Portfolio engine does not support decisions based on multiple properties. Only the first property will be considered.");
STORM_PRINT_AND_LOG("Portfolio engine picked the following settings: "<<std::endl<<"\tengine="<<mpi.engine<<"\t bisimulation="<<mpi.applyBisimulation<<"\t exact="<<(mpi.verificationValueType!=ModelProcessingInformation::ValueType::FinitePrecision)<<std::endl)
STORM_LOG_WARN("The settings picked by the portfolio engine (engine="<<mpi.engine<<", bisim="<<mpi.applyBisimulation<<", exact="<<(mpi.verificationValueType!=ModelProcessingInformation::ValueType::FinitePrecision)<<") are incompatible with this model. Falling back to sparse engine without bisimulation and floating point arithmetic.");
STORM_LOG_WARN("The model checking query does not seem to be supported for the selected engine. Storm will try to solve the query, but you will most likely get an error for at least one of the provided properties.");
STORM_LOG_THROW(engine==storm::settings::modules::CoreSettings::Engine::Sparse,storm::exceptions::InvalidSettingsException,"Can only use sparse engine with explicit input.");
STORM_LOG_THROW(mpi.engine==storm::utility::Engine::Sparse,storm::exceptions::InvalidSettingsException,"Can only use sparse engine with explicit input.");
STORM_LOG_WARN_COND(!model->containsZenoCycle(),"MA contains a Zeno cycle. Model checking results cannot be trusted.");
STORM_LOG_WARN_COND(!debugSettings.isAdditionalChecksSet()||!model->containsZenoCycle(),"MA contains a Zeno cycle. Model checking results cannot be trusted.");
if(model->isConvertibleToCtmc()){
STORM_LOG_WARN_COND(false,"MA is convertible to a CTMC, consider using a CTMC instead.");
STORM_LOG_WARN_COND(!bisimulationSettings.isWeakBisimulationSet(),"Weak bisimulation is currently not supported on DDs. Falling back to strong bisimulation.");
STORM_LOG_ASSERT(input.model,"Expected symbolic model description.");
STORM_LOG_THROW((std::is_same<ValueType,double>::value),storm::exceptions::NotSupportedException,"Exploration does not support other data-types than floating points.");
STORM_LOG_ASSERT(mpi.verificationValueType==ModelProcessingInformation::ValueType::FinitePrecision&&mpi.buildValueType==ModelProcessingInformation::ValueType::FinitePrecision&&(std::is_same<ValueType,double>::value),"Unexpected value type for Dd library cudd.");
STORM_LOG_THROW((std::is_same<ValueType,double>::value)&&mpi.buildValueType==ModelProcessingInformation::ValueType::Exact,storm::exceptions::InvalidArgumentException,"Unexpected combination of buildValueType and verificationValueType");
this->addOption(storm::settings::OptionBuilder(moduleName,locationVariablesOptionName,true,"Variables to export in the location").addArgument(storm::settings::ArgumentBuilder::createStringArgument("variables","A comma separated list of automaton and local variable names seperated by a dot, e.g. A.x,B.y.").setDefaultValueString("").build()).build());
@ -34,6 +35,7 @@ namespace storm {
this->addOption(storm::settings::OptionBuilder(moduleName,eliminateArraysOptionName,false,"If set, transforms the model such that array variables/expressions are eliminated.").build());
this->addOption(storm::settings::OptionBuilder(moduleName,eliminateFunctionsOptionName,false,"If set, transforms the model such that functions are eliminated.").build());
this->addOption(storm::settings::OptionBuilder(moduleName,replaceUnassignedVariablesWithConstantsOptionName,false,"If set, local and global variables that are (a) not assigned to some value and (b) have a known initial value are replaced by constants.").build());
this->addOption(storm::settings::OptionBuilder(moduleName,simplifyCompositionOptionName,false,"If set, attempts to simplify the system composition.").build());
STORM_LOG_THROW(engine==storm::settings::modules::CoreSettings::Engine::Sparse||engine==storm::settings::modules::CoreSettings::Engine::Hybrid||engine==storm::settings::modules::CoreSettings::Engine::Dd,storm::exceptions::InvalidSettingsException,"The selected engine is not supported for parametric models.");
STORM_LOG_THROW(mpi.engine==storm::utility::Engine::Sparse||mpi.engine==storm::utility::Engine::Hybrid||mpi.engine==storm::utility::Engine::Dd,storm::exceptions::InvalidSettingsException,"The selected engine is not supported for parametric models.");
STORM_LOG_WARN_COND(engine!=storm::settings::modules::CoreSettings::Engine::Dd||engine!=storm::settings::modules::CoreSettings::Engine::Hybrid||coreSettings.getDdLibraryType()==storm::dd::DdType::Sylvan,"The selected DD library does not support parametric models. Switching to Sylvan...");
STORM_LOG_WARN_COND(engine!=storm::utility::Engine::Dd||engine!=storm::utility::Engine::Hybrid||coreSettings.getDdLibraryType()==storm::dd::DdType::Sylvan,"The selected DD library does not support parametric models. Switching to Sylvan...");
// Parse and preprocess symbolic input (PRISM, JANI, properties, etc.)
STORM_LOG_THROW(nonEliminatedFeatures.empty(),storm::exceptions::NotSupportedException,"The used model feature(s) "<<nonEliminatedFeatures.toString()<<" is/are not in the list of allowed features.");
STORM_LOG_THROW(nonEliminatedFeatures.empty(),storm::exceptions::NotSupportedException,"The used model feature(s) "<<nonEliminatedFeatures.toString()<<" is/are not in the list of supported features.");
STORM_LOG_THROW(model->isOfType(storm::models::ModelType::Dtmc)||model->isOfType(storm::models::ModelType::Ctmc)||model->isOfType(storm::models::ModelType::Mdp)||model->isOfType(storm::models::ModelType::MarkovAutomaton),storm::exceptions::NotSupportedException,"Symbolic bisimulation minimization is currently only available for DTMCs, CTMCs, MDPs and MAs.");
STORM_LOG_THROW(bisimulationType==storm::storage::BisimulationType::Strong,storm::exceptions::NotSupportedException,"Currently only strong bisimulation is supported.");
STORM_LOG_THROW(false,storm::exceptions::NotSupportedException,"Symbolic bisimulation minimization is not supported for this combination of DD library and value type.");
STORM_LOG_THROW(false,storm::exceptions::NotSupportedException,"Transformation of symbolic "<<symbolicModel->getType()<<" to sparse model is not supported.");
// If there is no model to be build, we assume that the task of obtaining a model is either not required or can be accomplished somehow.
returntrue;
}
STORM_LOG_THROW(modelDescription.isPrismProgram()||modelDescription.isJaniModel(),storm::exceptions::UnexpectedException,"The model is neither PRISM nor Jani which is not expected.");
STORM_LOG_TRACE("Used local nondeterminism variables are "<<actionDd.getLowestLocalNondeterminismVariable()<<" to "<<actionDd.getHighestLocalNondeterminismVariable()<<".");
STORM_LOG_THROW(features.empty(),storm::exceptions::InvalidSettingsException,"The dd jani model builder does not support the following model feature(s): "<<features.toString()<<".");
storm::jani::ModelpreparedModel=model;
preparedModel.substituteFunctions();
preparedModel.simplifyComposition();
if(features.hasArrays()){
STORM_LOG_ERROR("The jani model still considers arrays. These should have been eliminated before calling the dd builder. The arrays are eliminated now, but occurrences in properties will not be handled properly.");
STORM_LOG_ERROR("The jani model still considers functions. These should have been substituted before calling the dd builder. The functions are substituted now, but occurrences in properties will not be handled properly.");
STORM_LOG_THROW(features.empty(),storm::exceptions::InvalidSettingsException,"The dd jani model builder does not support the following model feature(s): "<<features.toString()<<".");
// Lift the transient edge destinations. We can do so, as we know that there are no assignment levels (because that's not supported anyway).
STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(),storm::exceptions::InvalidPropertyException,"Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(),storm::exceptions::InvalidPropertyException,"Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(),storm::exceptions::InvalidPropertyException,"Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(),storm::exceptions::InvalidPropertyException,"Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(),storm::exceptions::NotImplementedException,"Currently step-bounded and reward-bounded properties on MarkovAutomatons are not supported.");
STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(),storm::exceptions::InvalidPropertyException,"Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(),storm::exceptions::InvalidPropertyException,"Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
// Check whether we consider a multi-objective formula
// For multi-objective model checking, each initial state requires an individual scheduler (in contrast to single objective model checking). Let's exclude multiple initial states.
// Check whether we consider a multi-objective formula
// For multi-objective model checking, each initial state requires an individual scheduler (in contrast to single objective model checking). Let's exclude multiple initial states.
STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(),storm::exceptions::InvalidPropertyException,"Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
STORM_LOG_THROW(pathFormula.getLeftSubformula().isTrueFormula(),storm::exceptions::NotImplementedException,"Only bounded properties of the form 'true U[t1, t2] phi' are currently supported.");
STORM_LOG_THROW(this->getModel().isClosed(),storm::exceptions::InvalidPropertyException,"Unable to compute time-bounded reachability probabilities in non-closed Markov automaton.");
STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(),storm::exceptions::NotImplementedException,"Currently step-bounded and reward-bounded properties on MAs are not supported.");
STORM_LOG_INFO("Selecting "<<storm::solver::toString(method)<<" as the solution technique for long-run properties to guarantee exact results. If you want to override this, please explicitly specify a different LRA method.");
// Allocate auxiliary memory that can be used during the iterations
std::vector<ValueType>maybeStatesValuesLower(maybeStates.getNumberOfSetBits(),storm::utility::zero<ValueType>());// should be zero initially
std::vector<ValueType>maybeStatesValuesWeightedUpper(maybeStates.getNumberOfSetBits(),storm::utility::zero<ValueType>());// should be zero initially
std::vector<ValueType>maybeStatesValuesUpper(maybeStates.getNumberOfSetBits(),storm::utility::zero<ValueType>());// should be zero initially
std::vector<ValueType>nextMarkovianStateValues=std::move(markovianExitRates);// At this point, the markovianExitRates are no longer needed, so we 'move' them away instead of allocating new memory
storm::utility::ProgressMeasurementprogressSteps("steps in iteration "+std::to_string(iteration)+" for "+std::string(computeLowerBound?"lower":"upper")+" bounds.");
progressSteps.setMaxCount(N);
progressSteps.startNewMeasurement(0);
boolfirstIteration=true;// The first iterations can be irrelevant, because they will only produce zeroes anyway.
// Iteration k = N is always non-relevant
for(int64_tk=N-1;k>=0;--k){
// Check whether the iteration is relevant, that is, whether it will contribute non-zero values to the overall result
if(computeLowerBound){
// Check whether the value for visiting a target state will be zero.
STORM_LOG_THROW(!requirements.hasEnabledCriticalRequirement(),storm::exceptions::UncheckedRequirementException,"Solver requirements "+requirements.getEnabledRequirementsAsString()+" not checked.");
/// Uniformizes the given matrix assuming that it is already uniform. The selfloopColumns indicate for each row, the column indices that correspond to the 'selfloops' for that row
STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(),storm::exceptions::UncheckedRequirementException,"The solver requirement "<<req.getEnabledRequirementsAsString()<<" has not been checked.");
}
// (6) Double lambda.
lambda*=2;
STORM_LOG_DEBUG("Increased lambda to "<<lambda<<", max diff is "<<maxNorm<<".");
STORM_LOG_INFO("Selecting 'LP' as the solution technique for long-run properties to guarantee exact results. If you want to override this, please explicitly specify a different LRA method.");
// Check whether we consider a multi-objective formula
// For multi-objective model checking, each state requires an individual scheduler (in contrast to single-objective model checking). Let's exclude that multiple states are relevant
// Check whether we consider a multi-objective formula
// For multi-objective model checking, each initial state requires an individual scheduler (in contrast to single-objective model checking). Let's exclude multiple initial states.
STORM_LOG_INFO("Selecting 'LP' as the solution technique for long-run properties to guarantee exact results. If you want to override this, please explicitly specify a different LRA method.");
this->addOption(storm::settings::OptionBuilder(moduleName,prismCompatibilityOptionName,false,"Enables PRISM compatibility. This may be necessary to process some PRISM models.").setShortName(prismCompatibilityOptionShortName).build());
this->addOption(storm::settings::OptionBuilder(moduleName,dontFixDeadlockOptionName,false,"If the model contains deadlock states, they need to be fixed by setting this option.").setShortName(dontFixDeadlockOptionShortName).setIsAdvanced().build());
this->addOption(storm::settings::OptionBuilder(moduleName,jitOptionName,false,"If set, the model is built using the JIT model builder.").build());
this->addOption(storm::settings::OptionBuilder(moduleName,fullModelBuildOptionName,false,"If set, include all rewards and labels.").build());
this->addOption(storm::settings::OptionBuilder(moduleName,applyNoMaxProgAssumptionOptionName,false,"If set, the maximum progress assumption is not applied while building the model (relevant for MAs)").setIsAdvanced().build());
this->addOption(storm::settings::OptionBuilder(moduleName,buildChoiceLabelOptionName,false,"If set, also build the choice labels").setIsAdvanced().build());
@ -57,10 +55,6 @@ namespace storm {
.addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("number","The number of bits.").addValidatorUnsignedInteger(ArgumentValidatorFactory::createUnsignedRangeValidatorExcluding(0,63)).setDefaultValueUnsignedInteger(32).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,engineOptionName,false,"Sets which engine is used for model building and model checking.").setShortName(engineOptionShortName)
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of the engine to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(engines)).setDefaultValueString("sparse").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,traceOptionName,false,"Print even more debug output.").build());
this->addOption(storm::settings::OptionBuilder(moduleName,additionalChecksOptionName,false,"If set, additional sanity checks are performed during execution.").build());
this->addOption(storm::settings::OptionBuilder(moduleName,logfileOptionName,false,"If specified, the log output will also be written to this file.").setShortName(logfileOptionShortName)
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename","The name of the file to write the log.").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,testOptionName,false,"Activate a test setting.").setIsAdvanced().build());
STORM_LOG_WARN_COND(storm::settings::getModule<storm::settings::modules::CoreSettings>().getEngine()==storm::settings::modules::CoreSettings::Engine::Exploration||!optionsSet,"Exploration engine is not selected, so setting options for it has no effect.");
STORM_LOG_WARN_COND(storm::settings::getModule<storm::settings::modules::CoreSettings>().getEngine()==storm::utility::Engine::Exploration||!optionsSet,"Exploration engine is not selected, so setting options for it has no effect.");
this->addOption(storm::settings::OptionBuilder(moduleName,solvingMethodOptionName,false,"Sets which min/max linear equation solving technique is preferred.").setIsAdvanced()
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of a min/max linear equation solving technique.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(minMaxSolvingTechniques)).setDefaultValueString("topological").build()).build());
@ -32,9 +31,6 @@ namespace storm {
this->addOption(storm::settings::OptionBuilder(moduleName,absoluteOptionName,false,"Sets whether the relative or the absolute error is considered for detecting convergence.").setIsAdvanced().build());
this->addOption(storm::settings::OptionBuilder(moduleName,markovAutomatonBoundedReachabilityMethodOptionName,false,"The method to use to solve bounded reachability queries on MAs.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of the method to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(maMethods)).setDefaultValueString("unifplus").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,valueIterationMultiplicationStyleOptionName,false,"Sets which method multiplication style to prefer for value iteration.").setIsAdvanced()
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of a multiplication style.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(multiplicationStyles)).setDefaultValueString("gaussseidel").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,techniqueOptionName,true,"The method to be used for solving linear equation systems with the native engine.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of the method to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(methods)).setDefaultValueString("jacobi").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,maximalIterationsOptionName,false,"The maximal number of iterations to perform before iterative solving is aborted.").setIsAdvanced().setShortName(maximalIterationsOptionShortName).addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count","The maximal iteration count.").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,precisionUpdateFactorOptionName,false,"Sets with which factor the precision of the inner value iteration is updated.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("factor","The factor.").setDefaultValueDouble(0.4).addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorExcluding(0.0,1.0)).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,useRelevantValuesForPrecisionUpdateOptionName,false,"Sets whether the precision of the inner value iteration is only based on the relevant values (i.e. initial states).").setIsAdvanced().build());
this->addOption(storm::settings::OptionBuilder(moduleName,maxVerificationIterationFactorOptionName,false,"Controls how many verification iterations are performed before guessing a new upper bound.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("factor","The factor.").setDefaultValueDouble(0.1).addValidatorDouble(ArgumentValidatorFactory::createDoubleGreaterValidator(0.0)).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,upperBoundGuessingFactorOptionName,false,"Sets with which factor the precision is multiplied to guess the upper bound.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("factor","The factor.").setDefaultValueDouble(1.0).addValidatorDouble(ArgumentValidatorFactory::createDoubleGreaterValidator(0.0)).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,upperBoundOnlyIterationsOptionName,false,"Sets the max. iterations OVI will only iterate over the upper bound.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createIntegerArgument("iter","The iterations.").setDefaultValueInteger(20000).addValidatorInteger(ArgumentValidatorFactory::createIntegerGreaterValidator(0)).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,maMethodOptionName,false,"The method to use to solve bounded reachability queries on MAs.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of the method to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(maMethods)).setDefaultValueString("unifplus").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,precisionOptionName,false,"The precision used for detecting convergence of iterative methods.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value","The precision to achieve.").setDefaultValueDouble(1e-06).addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorExcluding(0.0,1.0)).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,absoluteOptionName,false,"Sets whether the relative or the absolute error is considered for detecting convergence.").setIsAdvanced().build());
this->addOption(storm::settings::OptionBuilder(moduleName,unifPlusKappaOptionName,false,"The truncation factor used in unifPlus.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("kappa","The factor").setDefaultValueDouble(0.1).addValidatorDouble(ArgumentValidatorFactory::createDoubleRangeValidatorExcluding(0.0,1.0)).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,underlyingEquationSolverOptionName,true,"Sets which solver is considered for solving the underlying equation systems.").setIsAdvanced()
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of the used solver.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(linearEquationSolver)).setDefaultValueString("gmm++").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName,underlyingMinMaxMethodOptionName,true,"Sets which minmax method is considered for solving the underlying minmax equation systems.").setIsAdvanced()
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("name","The name of the used min max method.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(minMaxSolvingTechniques)).setDefaultValueString("value-iteration").build()).build());
STORM_LOG_ERROR_COND(!env.solver().isForceSoundness(),"This linear equation solver does not support sound computations. Using unsound methods now...");
STORM_LOG_ERROR_COND(!env.solver().isForceExact(),"This linear equation solver does not support exact computations. Using unsound methods now...");
STORM_LOG_INFO("Selecting 'sound value iteration' as the solution technique to guarantee sound results. If you want to override this, please explicitly specify a different method.");
method=MinMaxMethod::SoundValueIteration;
@ -57,17 +59,20 @@ namespace storm {
STORM_LOG_WARN("The selected solution method does not guarantee sound results.");
}
}
STORM_LOG_THROW(method==MinMaxMethod::ValueIteration||method==MinMaxMethod::PolicyIteration||method==MinMaxMethod::RationalSearch||method==MinMaxMethod::SoundValueIteration||method==MinMaxMethod::IntervalIteration||method==MinMaxMethod::ViToPi,storm::exceptions::InvalidEnvironmentException,"This solver does not support the selected method.");
STORM_LOG_THROW(method==MinMaxMethod::ValueIteration||method==MinMaxMethod::PolicyIteration||method==MinMaxMethod::RationalSearch||method==MinMaxMethod::SoundValueIteration||method==MinMaxMethod::IntervalIteration||method==MinMaxMethod::OptimisticValueIteration||method==MinMaxMethod::ViToPi,storm::exceptions::InvalidEnvironmentException,"This solver does not support the selected method.");
STORM_LOG_INFO("Selecting '"+toString(type)+"' as the linear equation solver to guarantee exact results. If you want to override this, please explicitly specify a different solver.");
}else{
STORM_LOG_WARN("The selected solver does not yield exact results.");
STORM_LOG_INFO("Selecting '"+toString(type)+"' as the linear equation solver to guarantee sound results. If you want to override this, please explicitly specify a different solver.");
STORM_LOG_INFO("Selecting '"+toString(method)+"' as the solution technique to guarantee sound results. If you want to override this, please explicitly specify a different method.");
xxxxxxxxxx