@ -12,6 +12,7 @@
# include "storm/utility/macros.h"
# include "storm/exceptions/InvalidSettingsException.h"
# include "storm/exceptions/InvalidStateException.h"
# include "storm/exceptions/NotImplementedException.h"
namespace storm {
namespace solver {
@ -112,6 +113,7 @@ namespace storm {
// Create a solver that we will use throughout the procedure. We will modify the matrix in each iteration.
auto solver = linearEquationSolverFactory - > create ( std : : move ( submatrix ) ) ;
setPrecisionRelativeOfLinearEquationSolver ( solver , this - > getPrecision ( ) , this - > getRelative ( ) ) ;
if ( this - > lowerBound ) {
solver - > setLowerBound ( this - > lowerBound . get ( ) ) ;
}
@ -231,15 +233,42 @@ namespace storm {
}
if ( this - > schedulerHint ) {
// Resolve the nondeterminism according to the scheduler hint and solve the resulting equation system.
// Resolve the nondeterminism according to the scheduler hint
storm : : storage : : SparseMatrix < ValueType > submatrix = this - > A . selectRowsFromRowGroups ( this - > schedulerHint - > getChoices ( ) , true ) ;
submatrix . convertToEquationSystem ( ) ;
storm : : utility : : vector : : selectVectorValues < ValueType > ( * auxiliaryRowGroupVector , this - > schedulerHint - > getChoices ( ) , this - > A . getRowGroupIndices ( ) , b ) ;
// Solve the resulting equation system.
// Note that the linEqSolver might consider a slightly different interpretation of "equalModuloPrecision". Hence, we iteratively increase its precision.
auto submatrixSolver = linearEquationSolverFactory - > create ( std : : move ( submatrix ) ) ;
submatrixSolver - > setCachingEnabled ( true ) ;
if ( this - > lowerBound ) { submatrixSolver - > setLowerBound ( this - > lowerBound . get ( ) ) ; }
if ( this - > upperBound ) { submatrixSolver - > setUpperBound ( this - > upperBound . get ( ) ) ; }
submatrixSolver - > solveEquations ( x , * auxiliaryRowGroupVector ) ;
ValueType linEqPrecision = this - > getPrecision ( ) ;
// Temporarily shrink the auxiliary row vector
auxiliaryRowVector - > resize ( A . getRowGroupCount ( ) ) ;
auxiliaryRowVector - > reserve ( A . getRowCount ( ) ) ;
uint_fast64_t hintIterations = 0 ;
bool vectorsNotEqual = false ;
do {
vectorsNotEqual = false ;
setPrecisionRelativeOfLinearEquationSolver ( submatrixSolver , linEqPrecision , this - > getRelative ( ) ) ;
submatrixSolver - > solveEquations ( x , * auxiliaryRowGroupVector ) ;
submatrixSolver - > multiply ( x , nullptr , * auxiliaryRowVector ) ;
linEqPrecision * = storm : : utility : : convertNumber < ValueType > ( 0.5 ) ;
+ + hintIterations ;
auto otherTmpResIt = auxiliaryRowVector - > begin ( ) ;
auto xIt = x . begin ( ) ;
for ( auto tmpResIt = auxiliaryRowGroupVector - > begin ( ) ; tmpResIt ! = auxiliaryRowGroupVector - > end ( ) ; + + tmpResIt ) {
if ( ! storm : : utility : : vector : : equalModuloPrecision ( * tmpResIt + * xIt , * otherTmpResIt + * xIt , this - > getPrecision ( ) , this - > getRelative ( ) ) ) {
vectorsNotEqual = true ;
break ;
}
+ + otherTmpResIt ; + + xIt ;
}
} while ( vectorsNotEqual ) ;
STORM_LOG_WARN_COND ( hintIterations = = 1 , " required " < < hintIterations < < " linear equation solver invokations to apply the scheduler hint " ) ;
auxiliaryRowVector - > resize ( A . getRowCount ( ) ) ;
}
std : : vector < ValueType > * newX = auxiliaryRowGroupVector . get ( ) ;
@ -348,6 +377,38 @@ namespace storm {
}
}
template < typename ValueType >
void StandardMinMaxLinearEquationSolver < ValueType > : : setPrecisionRelativeOfLinearEquationSolver ( std : : unique_ptr < storm : : solver : : LinearEquationSolver < ValueType > > & linEqSolver , ValueType precision , bool relative ) const {
auto * gmmSolver = dynamic_cast < storm : : solver : : GmmxxLinearEquationSolver < ValueType > * > ( linEqSolver . get ( ) ) ;
auto * nativeSolver = dynamic_cast < storm : : solver : : NativeLinearEquationSolver < ValueType > * > ( linEqSolver . get ( ) ) ;
auto * eigenSolver = dynamic_cast < storm : : solver : : EigenLinearEquationSolver < ValueType > * > ( linEqSolver . get ( ) ) ;
auto * eliminationSolver = dynamic_cast < storm : : solver : : EliminationLinearEquationSolver < ValueType > * > ( linEqSolver . get ( ) ) ;
if ( gmmSolver ) {
auto newSettings = gmmSolver - > getSettings ( ) ;
newSettings . setPrecision ( precision ) ;
newSettings . setRelativeTerminationCriterion ( relative ) ;
gmmSolver - > setSettings ( newSettings ) ;
} else if ( nativeSolver ) {
auto newSettings = nativeSolver - > getSettings ( ) ;
newSettings . setPrecision ( precision ) ;
newSettings . setRelativeTerminationCriterion ( relative ) ;
nativeSolver - > setSettings ( newSettings ) ;
} else if ( eigenSolver ) {
eigenSolver - > getSettings ( ) . setPrecision ( precision ) ;
// no relative flag for eigen solver
} else if ( eliminationSolver ) {
// elimination solver does not consider a precision so nothing to do
} else {
STORM_LOG_THROW ( false , storm : : exceptions : : NotImplementedException , " Changing the precision for the given linear equation solver type is not implemented " ) ;
}
}
template < >
void StandardMinMaxLinearEquationSolver < storm : : RationalNumber > : : setPrecisionRelativeOfLinearEquationSolver ( std : : unique_ptr < storm : : solver : : LinearEquationSolver < storm : : RationalNumber > > & linEqSolver , storm : : RationalNumber precision , bool relative ) const {
// Intentionally left empty
}
template < typename ValueType >
StandardMinMaxLinearEquationSolverSettings < ValueType > const & StandardMinMaxLinearEquationSolver < ValueType > : : getSettings ( ) const {
return settings ;