@ -555,8 +555,6 @@ namespace storm {
return converged ;
return converged ;
}
}
template < typename ValueType >
template < typename ValueType >
bool NativeLinearEquationSolver < ValueType > : : solveEquationsQuickSoundPower ( Environment const & env , std : : vector < ValueType > & x , std : : vector < ValueType > const & b ) const {
bool NativeLinearEquationSolver < ValueType > : : solveEquationsQuickSoundPower ( Environment const & env , std : : vector < ValueType > & x , std : : vector < ValueType > const & b ) const {
STORM_LOG_INFO ( " Solving linear equation system ( " < < x . size ( ) < < " rows) with NativeLinearEquationSolver (QuickPower) " ) ;
STORM_LOG_INFO ( " Solving linear equation system ( " < < x . size ( ) < < " rows) with NativeLinearEquationSolver (QuickPower) " ) ;
@ -577,53 +575,94 @@ namespace storm {
std : : vector < ValueType > * tmp = & x ;
std : : vector < ValueType > * tmp = & x ;
bool converged = false ;
bool terminate = false ;
uint64_t iterations = 0 ;
ValueType precision = storm : : utility : : convertNumber < ValueType > ( env . solver ( ) . native ( ) . getPrecision ( ) ) ;
ValueType precision = storm : : utility : : convertNumber < ValueType > ( env . solver ( ) . native ( ) . getPrecision ( ) ) ;
ValueType lowerValueBound , upperValueBound ;
bool relative = env . solver ( ) . native ( ) . getRelativeTerminationCriterion ( ) ;
bool relative = env . solver ( ) . native ( ) . getRelativeTerminationCriterion ( ) ;
if ( ! relative ) {
if ( ! relative ) {
precision * = storm : : utility : : convertNumber < ValueType > ( 2.0 ) ;
precision * = storm : : utility : : convertNumber < ValueType > ( 2.0 ) ;
}
}
uint64_t maxIter = env . solver ( ) . native ( ) . getMaximalNumberOfIterations ( ) ;
uint64_t maxIter = env . solver ( ) . native ( ) . getMaximalNumberOfIterations ( ) ;
//std::cout << *this->A << std::endl;
//std::cout << storm::utility::vector::toString(b) << std::endl;
//std::cout << "solving eq sys.. " << std::endl;
uint64_t iterations = 0 ;
bool converged = false ;
bool terminate = false ;
ValueType minValueBound , maxValueBound ;
uint64_t minIndex ( 0 ) , maxIndex ( 0 ) ;
uint64_t firstStayProb1Index = 0 ;
uint64_t firstIndexViolatingConvergence = this - > hasRelevantValues ( ) ? this - > getRelevantValues ( ) . getNextSetIndex ( 0 ) : 0 ;
this - > startMeasureProgress ( ) ;
this - > startMeasureProgress ( ) ;
uint64_t firstProb1Entry = 0 ;
while ( ! converged & & ! terminate & & iterations < maxIter ) {
while ( ! converged & & ! terminate & & iterations < maxIter ) {
// Apply step
this - > multiplier . multAdd ( * this - > A , * stepBoundedValues , & b , * tmp ) ;
this - > multiplier . multAdd ( * this - > A , * stepBoundedValues , & b , * tmp ) ;
std : : swap ( tmp , stepBoundedValues ) ;
std : : swap ( tmp , stepBoundedValues ) ;
this - > multiplier . multAdd ( * this - > A , * stepBoundedStayProbabilities , nullptr , * tmp ) ;
this - > multiplier . multAdd ( * this - > A , * stepBoundedStayProbabilities , nullptr , * tmp ) ;
std : : swap ( tmp , stepBoundedStayProbabilities ) ;
std : : swap ( tmp , stepBoundedStayProbabilities ) ;
for ( ; firstProb1Entry ! = stepBoundedStayProbabilities - > size ( ) ; + + firstProb1Entry ) {
//std::cout << "Iteration " << iterations << std::endl;
//std::cout << "x: " << storm::utility::vector::toString(*stepBoundedValues) << std::endl;
//std::cout << "y: " << storm::utility::vector::toString(*stepBoundedStayProbabilities) << std::endl;
// Check for convergence
// Phase 1: the probability to 'stay within the matrix' has to be < 1 at every state
for ( ; firstStayProb1Index ! = stepBoundedStayProbabilities - > size ( ) ; + + firstStayProb1Index ) {
static_assert ( NumberTraits < ValueType > : : IsExact | | std : : is_same < ValueType , double > : : value , " Considered ValueType not handled. " ) ;
static_assert ( NumberTraits < ValueType > : : IsExact | | std : : is_same < ValueType , double > : : value , " Considered ValueType not handled. " ) ;
if ( NumberTraits < ValueType > : : IsExact ) {
if ( NumberTraits < ValueType > : : IsExact ) {
if ( storm : : utility : : isOne ( stepBoundedStayProbabilities - > at ( firstProb1Entry ) ) ) {
if ( storm : : utility : : isOne ( stepBoundedStayProbabilities - > at ( firstStayProb1Index ) ) ) {
break ;
break ;
}
}
} else {
} else {
if ( storm : : utility : : isAlmostOne ( storm : : utility : : convertNumber < double > ( stepBoundedStayProbabilities - > at ( firstProb1Entry ) ) ) ) {
if ( storm : : utility : : isAlmostOne ( storm : : utility : : convertNumber < double > ( stepBoundedStayProbabilities - > at ( firstStayProb1Index ) ) ) ) {
break ;
break ;
// std::cout << "In Phase 1" << std::endl;
}
}
}
}
}
}
if ( firstProb1Entry = = stepBoundedStayProbabilities - > size ( ) ) {
auto valIt = stepBoundedValues - > begin ( ) ;
auto valIte = stepBoundedValues - > end ( ) ;
auto probIt = stepBoundedStayProbabilities - > begin ( ) ;
STORM_LOG_ASSERT ( ! storm : : utility : : isOne ( * probIt ) , " Did not expect staying-probability 1 at this point. " ) ;
lowerValueBound = * valIt / ( storm : : utility : : one < ValueType > ( ) - * probIt ) ;
upperValueBound = lowerValueBound ;
ValueType largestStayProb = * probIt ;
for ( ; valIt ! = valIte ; + + valIt , + + probIt ) {
STORM_LOG_ASSERT ( ! storm : : utility : : isOne ( * probIt ) , " Did not expect staying-probability 1 at this point. " ) ;
ValueType currentBound = * valIt / ( storm : : utility : : one < ValueType > ( ) - * probIt ) ;
lowerValueBound = std : : min ( lowerValueBound , currentBound ) ;
upperValueBound = std : : max ( upperValueBound , currentBound ) ;
largestStayProb = std : : max ( largestStayProb , * probIt ) ;
if ( firstStayProb1Index = = stepBoundedStayProbabilities - > size ( ) ) {
STORM_LOG_ASSERT ( ! std : : any_of ( stepBoundedStayProbabilities - > begin ( ) , stepBoundedStayProbabilities - > end ( ) , [ ] ( ValueType value ) { return storm : : utility : : isOne ( value ) ; } ) , " Did not expect staying-probability 1 at this point. " ) ;
// Phase 2: the difference between lower and upper bound has to be < precision at every (relevant) value
// std::cout << "In Phase 2" << std::endl;
// First check with (possibly too tight) bounds from a previous iteration. Only compute the actual bounds if this first check passes.
minValueBound = stepBoundedValues - > at ( minIndex ) / ( storm : : utility : : one < ValueType > ( ) - stepBoundedStayProbabilities - > at ( minIndex ) ) ;
maxValueBound = stepBoundedValues - > at ( maxIndex ) / ( storm : : utility : : one < ValueType > ( ) - stepBoundedStayProbabilities - > at ( maxIndex ) ) ;
ValueType const & stayProb = stepBoundedStayProbabilities - > at ( firstIndexViolatingConvergence ) ;
if ( stayProb * ( maxValueBound - minValueBound ) < precision ) {
// Compute the actual bounds now
auto valIt = stepBoundedValues - > begin ( ) ;
auto valIte = stepBoundedValues - > end ( ) ;
auto probIt = stepBoundedStayProbabilities - > begin ( ) ;
for ( uint64_t index = 0 ; valIt ! = valIte ; + + valIt , + + probIt , + + index ) {
ValueType currentBound = * valIt / ( storm : : utility : : one < ValueType > ( ) - * probIt ) ;
if ( currentBound < minValueBound ) {
minIndex = index ;
minValueBound = std : : move ( currentBound ) ;
} else if ( currentBound > maxValueBound ) {
maxIndex = index ;
maxValueBound = std : : move ( currentBound ) ;
}
}
if ( stayProb * ( maxValueBound - minValueBound ) < precision ) {
// The current index satisfies the desired bound. We now move to the next index that violates it
do {
+ + firstIndexViolatingConvergence ;
if ( this - > hasRelevantValues ( ) ) {
firstIndexViolatingConvergence = this - > getRelevantValues ( ) . getNextSetIndex ( firstIndexViolatingConvergence ) ;
}
if ( firstIndexViolatingConvergence = = stepBoundedStayProbabilities - > size ( ) ) {
converged = true ;
break ;
} else if ( stepBoundedStayProbabilities - > at ( firstIndexViolatingConvergence ) * ( maxValueBound - minValueBound ) > = precision ) {
// not converged yet
break ;
}
} while ( true ) ;
}
}
}
STORM_LOG_ASSERT ( ! relative , " Relative termination criterion not implemented currently. " ) ;
STORM_LOG_ASSERT ( ! relative , " Relative termination criterion not implemented currently. " ) ;
converged = largestStayProb * ( upperValueBound - lowerValueBound ) < precision ;
STORM_LOG_INFO_COND ( ! converged , " Lower value bound: " < < lowerValueBound < < " Upper value bound: " < < upperValueBound < < " Largest stay prob.: " < < largestStayProb ) ;
}
}
// Potentially show progress.
// Potentially show progress.
@ -635,7 +674,7 @@ namespace storm {
}
}
// Finally set up the solution vector
// Finally set up the solution vector
ValueType meanBound = ( upperValueBound - lower ValueBound) / storm : : utility : : convertNumber < ValueType > ( 2.0 ) ;
ValueType meanBound = ( maxValueBound + min ValueBound) / storm : : utility : : convertNumber < ValueType > ( 2.0 ) ;
storm : : utility : : vector : : applyPointwise ( * stepBoundedValues , * stepBoundedStayProbabilities , x , [ & meanBound ] ( ValueType const & v , ValueType const & p ) { return v + p * meanBound ; } ) ;
storm : : utility : : vector : : applyPointwise ( * stepBoundedValues , * stepBoundedStayProbabilities , x , [ & meanBound ] ( ValueType const & v , ValueType const & p ) { return v + p * meanBound ; } ) ;
if ( ! this - > isCachingEnabled ( ) ) {
if ( ! this - > isCachingEnabled ( ) ) {
@ -643,6 +682,7 @@ namespace storm {
}
}
this - > logIterations ( converged , terminate , iterations ) ;
this - > logIterations ( converged , terminate , iterations ) ;
STORM_LOG_INFO ( " Quick Power Iteration terminated with lower value bound " < < minValueBound < < " and upper value bound " < < maxValueBound < < " . " ) ;
return converged ;
return converged ;