@ -5,8 +5,8 @@
* Author : Christian Dehnert
*/
# ifndef STORM_MODELCHECKER_GMMXXDTMC PRCTLMODELCHECKER_H_
# define STORM_MODELCHECKER_GMMXXDTMC PRCTLMODELCHECKER_H_
# ifndef STORM_MODELCHECKER_GMMXXMDP PRCTLMODELCHECKER_H_
# define STORM_MODELCHECKER_GMMXXMDP PRCTLMODELCHECKER_H_
# include <cmath>
@ -36,12 +36,12 @@ namespace modelChecker {
* A model checking engine that makes use of the gmm + + backend .
*/
template < class Type >
class GmmxxDtmc PrctlModelChecker : public MdpPrctlModelChecker < Type > {
class GmmxxMdp PrctlModelChecker : public MdpPrctlModelChecker < Type > {
public :
explicit GmmxxDtmc PrctlModelChecker ( storm : : models : : Mdp < Type > & mdp ) : MdpPrctlModelChecker < Type > ( mdp ) { }
explicit GmmxxMdp PrctlModelChecker ( storm : : models : : Mdp < Type > & mdp ) : MdpPrctlModelChecker < Type > ( mdp ) { }
virtual ~ GmmxxDtmc PrctlModelChecker ( ) { }
virtual ~ GmmxxMdp PrctlModelChecker ( ) { }
virtual std : : vector < Type > * checkBoundedUntil ( const storm : : formula : : BoundedUntil < Type > & formula ) const {
/ / First , we need to compute the states that satisfy the sub - formulas of the until - formula .
@ -67,13 +67,13 @@ public:
/ / Create vector for result of multiplication , which is reduced to the result vector after
/ / each multiplication .
std : : vector < Type > * multiplyResult = new std : : vector < Type > ( this - > getModel ( ) . getTransitionMatrix ( ) . getRowCount ( ) ) ;
std : : vector < Type > * multiplyResult = new std : : vector < Type > ( this - > getModel ( ) . getTransitionMatrix ( ) - > getRowCount ( ) ) ;
/ / 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 , * multiplyResult ) ;
if ( minimumOperatorStack . top ( ) ) {
if ( this - > minimumOperatorStack . top ( ) ) {
storm : : utility : : reduceVectorMin ( * multiplyResult , result , * nondeterministicChoiceIndices ) ;
} else {
storm : : utility : : reduceVectorMax ( * multiplyResult , result , * nondeterministicChoiceIndices ) ;
@ -103,7 +103,7 @@ public:
delete nextStates ;
/ / Create resulting vector .
std : : vector < Type > * temporaryResult = new std : : vector < Type > ( this - > getModel ( ) . getTransitionMatrix ( ) . getRowCount ( ) ) ;
std : : vector < Type > * temporaryResult = new std : : vector < Type > ( this - > getModel ( ) . getTransitionMatrix ( ) - > getRowCount ( ) ) ;
/ / Perform the actual computation , namely matrix - vector multiplication .
gmm : : mult ( * gmmxxMatrix , * result , * temporaryResult ) ;
@ -112,7 +112,7 @@ public:
/ / vector properly .
std : : shared_ptr < std : : vector < uint_fast64_t > > nondeterministicChoiceIndices = this - > getModel ( ) . getNondeterministicChoiceIndices ( ) ;
if ( minimumOperatorStack . top ( ) ) {
if ( this - > minimumOperatorStack . top ( ) ) {
storm : : utility : : reduceVectorMin ( * temporaryResult , result , * nondeterministicChoiceIndices ) ;
} else {
storm : : utility : : reduceVectorMax ( * temporaryResult , result , * nondeterministicChoiceIndices ) ;
@ -133,7 +133,7 @@ public:
/ / all states that have probability 0 and 1 of satisfying the until - formula .
storm : : storage : : BitVector statesWithProbability0 ( this - > getModel ( ) . getNumberOfStates ( ) ) ;
storm : : storage : : BitVector statesWithProbability1 ( this - > getModel ( ) . getNumberOfStates ( ) ) ;
if ( minimumOperatorStack . top ( ) ) {
if ( this - > minimumOperatorStack . top ( ) ) {
storm : : utility : : GraphAnalyzer : : performProb01Min ( this - > getModel ( ) , * leftStates , * rightStates , & statesWithProbability0 , & statesWithProbability1 ) ;
} else {
storm : : utility : : GraphAnalyzer : : performProb01Max ( this - > getModel ( ) , * leftStates , * rightStates , & statesWithProbability0 , & statesWithProbability1 ) ;
@ -152,32 +152,36 @@ public:
std : : vector < Type > * result = new std : : vector < Type > ( this - > getModel ( ) . getNumberOfStates ( ) ) ;
/ / Only try to solve system if there are states for which the probability is unknown .
uint_fast64_t mayBeStatesSetBitCount = maybeStates . getNumberOfSetBits ( ) ;
if ( mayBeStatesSetBitCount > 0 ) {
/ / Now we can eliminate the rows and columns from the original transition probability matrix .
storm : : storage : : SparseMatrix < Type > * submatrix = this - > getModel ( ) . getTransitionMatrix ( ) - > getSubmatrix ( maybeStates ) ;
uint_fast64_t maybeStatesSetBitCount = maybeStates . getNumberOfSetBits ( ) ;
if ( maybeStatesSetBitCount > 0 ) {
/ / First , we can eliminate the rows and columns from the original transition probability matrix for states
/ / whose probabilities are already known .
storm : : storage : : SparseMatrix < Type > * submatrix = this - > getModel ( ) . getTransitionMatrix ( ) - > getSubmatrix ( maybeStates , * this - > getModel ( ) . getNondeterministicChoiceIndices ( ) ) ;
/ / Transform the submatrix to the gmm + + format to use its solvers .
/ / Get the " new " nondeterministic choice indices for the submatrix .
std : : shared_ptr < std : : vector < uint_fast64_t > > subNondeterministicChoiceIndices = this - > computeNondeterministicChoiceIndicesForConstraint ( maybeStates ) ;
/ / Transform the submatrix to the gmm + + format to use its capabilities .
gmm : : csr_matrix < Type > * gmmxxMatrix = storm : : adapters : : GmmxxAdapter : : toGmmxxSparseMatrix < Type > ( * submatrix ) ;
delete submatrix ;
/ / Initialize the x vector with 0.5 for each element . This is the initial guess for
/ / iteratively solving the equations .
std : : vector < Type > x ( mayBeStatesSetBitCount , Type ( 0.5 ) ) ;
/ / Create vector for results for maybe states .
std : : vector < Type > * x = new std : : vector < Type > ( maybeStatesSetBitCount ) ;
/ / 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 < Type > b ( mayBeStatesSetBitCount ) ;
this - > getModel ( ) . getTransitionMatrix ( ) - > getConstrainedRowCountVector ( maybeStates , statesWithProbability1 , & b ) ;
std : : vector < Type > b ( submatrix - > getRowCount ( ) ) ;
this - > getModel ( ) . getTransitionMatrix ( ) - > getConstrainedRowSumVector ( maybeStates , * this - > getModel ( ) . getNondeterministicChoiceIndices ( ) , statesWithProbability1 , & b ) ;
delete submatrix ;
/ / Solve the corresponding system of linear equations .
this - > solveEquationSystem ( * gmmxxMatrix , x , b ) ;
/ / Solve the corresponding system of equations .
this - > solveEquationSystem ( * gmmxxMatrix , x , b , * subNondeterministicChoiceIndices ) ;
/ / Set values of resulting vector according to result .
storm : : utility : : setVectorValues < Type > ( result , maybeStates , x ) ;
storm : : utility : : setVectorValues < Type > ( result , maybeStates , * x ) ;
/ / Delete temporary matrix .
/ / Delete temporary matrix and vector .
delete gmmxxMatrix ;
delete x ;
}
/ / Set values of resulting vector that are known exactly .
@ -272,7 +276,8 @@ public:
/ / Determine which states have a reward of infinity by definition .
storm : : storage : : BitVector infinityStates ( this - > getModel ( ) . getNumberOfStates ( ) ) ;
storm : : storage : : BitVector trueStates ( this - > getModel ( ) . getNumberOfStates ( ) , true ) ;
storm : : utility : : GraphAnalyzer : : performProb1 ( this - > getModel ( ) , trueStates , * targetStates , & infinityStates ) ;
/ / TODO : just commented out to make it compile
/ / storm : : utility : : GraphAnalyzer : : performProb1 ( this - > getModel ( ) , trueStates , * targetStates , & infinityStates ) ;
infinityStates . complement ( ) ;
/ / Create resulting vector .
@ -325,7 +330,8 @@ public:
}
/ / Solve the corresponding system of linear equations .
this - > solveLinearEquationSystem ( * gmmxxMatrix , x , * b ) ;
/ / TODO : just commented out to make it compile
/ / this - > solveEquationSystem ( * gmmxxMatrix , x , * b ) ;
/ / Set values of resulting vector according to result .
storm : : utility : : setVectorValues < Type > ( result , maybeStates , x ) ;
@ -344,31 +350,6 @@ public:
return result ;
}
/*!
* Returns the name of this module .
* @ return The name of this module .
*/
static std : : string getModuleName ( ) {
return " gmm++nondet " ;
}
/*!
* 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 ( ) ( " lemaxiter " , boost : : program_options : : value < unsigned > ( ) - > default_value ( 10000 ) , " Sets the maximal number of iterations for iterative equation solving. " ) ;
desc - > add_options ( ) ( " precision " , boost : : program_options : : value < double > ( ) - > default_value ( 10e-6 ) , " Sets the precision for iterative linear equation solving. " ) ;
}
private :
/*!
* Solves the given equation system under the given parameters using the power method .
@ -380,25 +361,70 @@ private:
* @ return The solution of the system of linear equations in form of the elements of the vector
* x .
*/
void solveLinear EquationSystem ( gmm : : csr_matrix < Type > const & A , std : : vector < Type > & x , std : : vector < Type > const & b ) const {
/ / Get the settings object to customize linear solving .
void solveEquationSystem ( gmm : : csr_matrix < Type > const & A , std : : vector < Type > * x , std : : vector < Type > const & b , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices ) const {
/ / Get the settings object to customize solving .
storm : : settings : : Settings * s = storm : : settings : : instance ( ) ;
/ / Get relevant user - defined settings for solving the equations
double precison = s - > get < double > ( " precision " ) ;
unsigned maxIterations = s - > get < unsigned > ( " lemaxiter " ) ;
/ / Get relevant user - defined settings for solving the equations .
double precision = s - > get < double > ( " precision " ) ;
unsigned maxIterations = s - > get < unsigned > ( " maxiter " ) ;
bool relative = s - > get < bool > ( " relative " ) ;
/ / Set up the environment for the power method .
std : : vector < Type > * temporaryResult = new std : : vector < Type > ( b . size ( ) ) ;
std : : vector < Type > * newX = new std : : vector < Type > ( x - > size ( ) ) ;
std : : vector < Type > * swap = nullptr ;
bool converged = false ;
uint_fast64_t iterations = 0 ;
/ / Proceed with the iterations as long as the method did not converge or reach the
/ / user - specified maximum number of iterations .
while ( ! converged & & iterations < maxIterations ) {
/ / Compute x ' = A * x + b .
gmm : : mult ( A , * x , * temporaryResult ) ;
gmm : : add ( b , * temporaryResult ) ;
/ / Reduce the vector x ' by applying min / max for all non - deterministic choices .
if ( this - > minimumOperatorStack . top ( ) ) {
storm : : utility : : reduceVectorMin ( * temporaryResult , newX , nondeterministicChoiceIndices ) ;
} else {
storm : : utility : : reduceVectorMax ( * temporaryResult , newX , nondeterministicChoiceIndices ) ;
}
/ / Determine whether the method converged .
converged = storm : : utility : : equalModuloPrecision ( * x , * newX , precision , relative ) ;
/ / Update environment variables .
swap = x ;
x = newX ;
newX = swap ;
+ + iterations ;
}
delete temporaryResult ;
/ / Check if the solver converged and issue a warning otherwise .
if ( iter . converged ( ) ) {
LOG4CPLUS_INFO ( logger , " Iterative solver converged after " < < iter . get_iteration ( ) < < " iterations. " ) ;
if ( converged ) {
LOG4CPLUS_INFO ( logger , " Iterative solver converged after " < < iterations < < " iterations. " ) ;
} else {
LOG4CPLUS_WARN ( logger , " Iterative solver did not converge. " ) ;
}
}
std : : shared_ptr < std : : vector < uint_fast64_t > > computeNondeterministicChoiceIndicesForConstraint ( storm : : storage : : BitVector constraint ) const {
std : : shared_ptr < std : : vector < uint_fast64_t > > nondeterministicChoiceIndices = this - > getModel ( ) . getNondeterministicChoiceIndices ( ) ;
std : : shared_ptr < std : : vector < uint_fast64_t > > subNondeterministicChoiceIndices ( new std : : vector < uint_fast64_t > ( constraint . getNumberOfSetBits ( ) + 1 ) ) ;
uint_fast64_t currentRowCount = 0 ;
uint_fast64_t currentIndexCount = 1 ;
( * subNondeterministicChoiceIndices ) [ 0 ] = 0 ;
for ( auto index : constraint ) {
( * subNondeterministicChoiceIndices ) [ currentIndexCount ] = currentRowCount + ( * nondeterministicChoiceIndices ) [ index + 1 ] - ( * nondeterministicChoiceIndices ) [ index ] ;
currentRowCount + = ( * nondeterministicChoiceIndices ) [ index + 1 ] - ( * nondeterministicChoiceIndices ) [ index ] ;
+ + currentIndexCount ;
}
( * subNondeterministicChoiceIndices ) [ constraint . getNumberOfSetBits ( ) ] = currentRowCount ;
return subNondeterministicChoiceIndices ;
}
} ;
@ -406,4 +432,4 @@ private:
} / / namespace storm
# endif /* STORM_MODELCHECKER_GMMXXDTMC PRCTLMODELCHECKER_H_ */
# endif /* STORM_MODELCHECKER_GMMXXMDP PRCTLMODELCHECKER_H_ */