@ -28,19 +28,18 @@ namespace storm {
namespace parser {
/*!
* @ brief Perform first pass through the file and obtain number of
* non - zero cells and maximum node id .
*
* This method does the first pass through the . tra file and computes
* the number of non - zero elements .
* It also calculates the maximum node id and stores it in maxnode .
*
* @ return The number of non - zero elements
* @ param buf Data to scan . Is expected to be some char array .
* @ param maxnode Is set to highest id of all nodes .
*/
storm : : storage : : SparseMatrix < double > DeterministicSparseTransitionParser : : parseDeterministicTransitions ( std : : string const & filename , bool insertDiagonalEntriesIfMissing ) {
return DeterministicSparseTransitionParser : : parse ( filename , false , insertDiagonalEntriesIfMissing ) ;
}
storm : : storage : : SparseMatrix < double > DeterministicSparseTransitionParser : : parseDeterministicTransitionRewards ( std : : string const & filename , RewardMatrixInformationStruct const & rewardMatrixInformation ) {
return DeterministicSparseTransitionParser : : parse ( filename , true , false , rewardMatrixInformation ) ;
}
DeterministicSparseTransitionParser : : FirstPassResult DeterministicSparseTransitionParser : : firstPass ( char * buf , SupportedLineEndingsEnum lineEndings , bool insertDiagonalEntriesIfMissing ) {
DeterministicSparseTransitionParser : : FirstPassResult result ;
// Skip the format hint if it is there.
@ -107,220 +106,156 @@ DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransiti
return result ;
}
/*!
* Reads a . tra file and produces a sparse matrix representing the described Markov Chain .
*
* Matrices created with this method have to be freed with the delete operator .
* @ param filename input . tra file ' s name .
* @ return a pointer to the created sparse matrix .
*/
storm : : storage : : SparseMatrix < double > DeterministicSparseTransitionParser : : parseDeterministicTransitions ( std : : string const & filename , bool insertDiagonalEntriesIfMissing ) {
storm : : storage : : SparseMatrix < double > DeterministicSparseTransitionParser : : parse ( std : : string const & filename , bool rewardFile , bool insertDiagonalEntriesIfMissing , RewardMatrixInformationStruct const & rewardMatrixInformation ) {
// Enforce locale where decimal point is '.'.
setlocale ( LC_NUMERIC , " C " ) ;
if ( ! fileExistsAndIsReadable ( filename . c_str ( ) ) ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : File does not exist or is not readable. " ) ;
throw storm : : exceptions : : FileIoException ( ) < < " The supplied Transition input file \" " < < filename < < " \" does not exist or is not readable by this process. " ;
}
setlocale ( LC_NUMERIC , " C " ) ;
// Find out about the used line endings.
SupportedLineEndingsEnum lineEndings = findUsedLineEndings ( filename , true ) ;
// Open file.
MappedFile file ( filename . c_str ( ) ) ;
char * buf = file . data ;
// Perform first pass, i.e. count entries that are not zero.
DeterministicSparseTransitionParser : : FirstPassResult firstPass = DeterministicSparseTransitionParser : : firstPass ( file . data , lineEndings , insertDiagonalEntriesIfMissing ) ;
LOG4CPLUS_INFO ( logger , " First pass on " < < filename < < " shows " < < firstPass . numberOfNonzeroEntries < < " NonZeros. " ) ;
// If first pass returned zero, the file format was wrong.
if ( firstPass . numberOfNonzeroEntries = = 0 ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : empty or erroneous file format. " ) ;
throw storm : : exceptions : : WrongFormatException ( ) ;
}
// Perform second pass.
// Skip the format hint if it is there.
buf = trimWhitespaces ( buf ) ;
if ( buf [ 0 ] ! = ' 0 ' ) {
buf = storm : : parser : : forwardToNextLine ( buf , lineEndings ) ;
}
if ( ! fileExistsAndIsReadable ( filename . c_str ( ) ) ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : File does not exist or is not readable. " ) ;
throw storm : : exceptions : : FileIoException ( ) < < " The supplied Transition input file \" " < < filename < < " \" does not exist or is not readable by this process. " ;
}
// Creating matrix builder here.
// The number of non-zero elements is computed by firstPass().
// The contents are inserted during the readout of the file, below.
// The actual matrix will be build once all contents are inserted.
storm : : storage : : SparseMatrixBuilder < double > resultMatrix ( firstPass . highestStateIndex + 1 , firstPass . highestStateIndex + 1 , firstPass . numberOfNonzeroEntries ) ;
// Find out about the used line endings.
SupportedLineEndingsEnum lineEndings = findUsedLineEndings ( filename , true ) ;
uint_fast64_t row , col , lastRow = 0 ;
double val ;
bool fixDeadlocks = storm : : settings : : Settings : : getInstance ( ) - > isSet ( " fixDeadlocks " ) ;
bool hadDeadlocks = false ;
bool rowHadDiagonalEntry = false ;
// Open file.
MappedFile file ( filename . c_str ( ) ) ;
char * buf = file . data ;
// Perform first pass, i.e. count entries that are not zero.
// Read all transitions from file. Note that we assume that the
// transitions are listed in canonical order, otherwise this will not
// work, i.e. the values in the matrix will be at wrong places.
while ( buf [ 0 ] ! = ' \0 ' ) {
DeterministicSparseTransitionParser : : FirstPassResult firstPass = DeterministicSparseTransitionParser : : firstPass ( file . data , lineEndings , insertDiagonalEntriesIfMissing ) ;
// Read next transition.
row = checked_strtol ( buf , & buf ) ;
col = checked_strtol ( buf , & buf ) ;
val = checked_strtod ( buf , & buf ) ;
LOG4CPLUS_INFO ( logger , " First pass on " < < filename < < " shows " < < firstPass . numberOfNonzeroEntries < < " NonZeros. " ) ;
// Read probability of this transition.
// Check, if the value is a probability, i.e. if it is between 0 and 1.
if ( ( val < 0.0 ) | | ( val > 1.0 ) ) {
LOG4CPLUS_ERROR ( logger , " Expected a positive probability but got \" " < < val < < " \" . " ) ;
// If first pass returned zero, the file format was wrong.
if ( firstPass . numberOfNonzeroEntries = = 0 ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : empty or erroneous file format. " ) ;
throw storm : : exceptions : : WrongFormatException ( ) ;
}
// Test if we moved to a new row.
// Handle all incomplete or skipped rows.
if ( lastRow ! = row ) {
if ( ! rowHadDiagonalEntry ) {
if ( insertDiagonalEntriesIfMissing ) {
resultMatrix . addNextValue ( lastRow , lastRow , storm : : utility : : constantZero < double > ( ) ) ;
LOG4CPLUS_DEBUG ( logger , " While parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. Inserted a 0-transition. (1) " ) ;
} else {
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. " ) ;
}
// No increment for lastRow.
rowHadDiagonalEntry = true ;
}
for ( uint_fast64_t skippedRow = lastRow + 1 ; skippedRow < row ; + + skippedRow ) {
hadDeadlocks = true ;
if ( fixDeadlocks ) {
resultMatrix . addNextValue ( skippedRow , skippedRow , storm : : utility : : constantOne < double > ( ) ) ;
rowHadDiagonalEntry = true ;
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < skippedRow < < " has no outgoing transitions. A self-loop was inserted. " ) ;
} else {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : state " < < skippedRow < < " has no outgoing transitions. " ) ;
// Before throwing the appropriate exception we will give notice of all deadlock states.
}
}
lastRow = row ;
rowHadDiagonalEntry = false ;
}
// Perform second pass.
if ( col = = row ) {
rowHadDiagonalEntry = true ;
// Skip the format hint if it is there.
buf = trimWhitespaces ( buf ) ;
if ( buf [ 0 ] ! = ' 0 ' ) {
buf = storm : : parser : : forwardToNextLine ( buf , lineEndings ) ;
}
if ( col > row & & ! rowHadDiagonalEntry ) {
if ( insertDiagonalEntriesIfMissing ) {
resultMatrix . addNextValue ( row , row , storm : : utility : : constantZero < double > ( ) ) ;
LOG4CPLUS_DEBUG ( logger , " While parsing " < < filename < < " : state " < < row < < " has no transition to itself. Inserted a 0-transition. (2) " ) ;
if ( rewardFile ) {
// The reward matrix should match the size of the transition matrix.
if ( firstPass . highestStateIndex + 1 > rewardMatrixInformation . rowCount | | firstPass . highestStateIndex + 1 > rewardMatrixInformation . columnCount ) {
LOG4CPLUS_ERROR ( logger , " Reward matrix has more rows or columns than transition matrix. " ) ;
throw storm : : exceptions : : WrongFormatException ( ) < < " Reward matrix has more rows or columns than transition matrix. " ;
} else {
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < row < < " has no transition to itself. " ) ;
// If we found the right number of states or less, we set it to the number of states represented by the transition matrix.
firstPass . highestStateIndex = rewardMatrixInformation . rowCount - 1 ;
}
rowHadDiagonalEntry = true ;
}
resultMatrix . addNextValue ( row , col , val ) ;
buf = trimWhitespaces ( buf ) ;
}
if ( ! rowHadDiagonalEntry ) {
if ( insertDiagonalEntriesIfMissing ) {
resultMatrix . addNextValue ( lastRow , lastRow , storm : : utility : : constantZero < double > ( ) ) ;
LOG4CPLUS_DEBUG ( logger , " While parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. Inserted a 0-transition. (3) " ) ;
} else {
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. " ) ;
}
}
// If we encountered deadlock and did not fix them, now is the time to throw the exception.
if ( ! fixDeadlocks & & hadDeadlocks ) throw storm : : exceptions : : WrongFormatException ( ) < < " Some of the nodes had deadlocks. You can use --fixDeadlocks to insert self-loops on the fly. " ;
return resultMatrix . build ( ) ;
}
/*!
* Reads a . tra file and produces a sparse matrix representing the described Markov Chain .
*
* Matrices created with this method have to be freed with the delete operator .
* @ param filename input . tra file ' s name .
* @ return a pointer to the created sparse matrix .
*/
storm : : storage : : SparseMatrix < double > DeterministicSparseTransitionParser : : parseDeterministicTransitionRewards ( std : : string const & filename , RewardMatrixInformationStruct const & rewardMatrixInformation ) {
// Enforce locale where decimal point is '.'.
setlocale ( LC_NUMERIC , " C " ) ;
if ( ! fileExistsAndIsReadable ( filename . c_str ( ) ) ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : File does not exist or is not readable. " ) ;
throw storm : : exceptions : : FileIoException ( ) < < " The supplied Transition input file \" " < < filename < < " \" does not exist or is not readable by this process. " ;
}
// Creating matrix builder here.
// The actual matrix will be build once all contents are inserted.
storm : : storage : : SparseMatrixBuilder < double > resultMatrix ( firstPass . highestStateIndex + 1 , firstPass . highestStateIndex + 1 , firstPass . numberOfNonzeroEntries ) ;
// Find out about the used line endings.
SupportedLineEndingsEnum lineEndings = findUsedLineEndings ( filename , true ) ;
uint_fast64_t row , col , lastRow = 0 ;
double val ;
bool fixDeadlocks = storm : : settings : : Settings : : getInstance ( ) - > isSet ( " fixDeadlocks " ) ;
bool hadDeadlocks = false ;
bool rowHadDiagonalEntry = false ;
// Open file.
MappedFile file ( filename . c_str ( ) ) ;
char * buf = file . data ;
// Perform first pass, i.e. count entries that are not zero.
// Read all transitions from file. Note that we assume that the
// transitions are listed in canonical order, otherwise this will not
// work, i.e. the values in the matrix will be at wrong places.
DeterministicSparseTransitionParser : : FirstPassResult firstPass = DeterministicSparseTransitionParser : : firstPass ( file . data , lineEndings , false ) ;
// Different parsing routines for transition systems and transition rewards.
if ( rewardFile ) {
while ( buf [ 0 ] ! = ' \0 ' ) {
LOG4CPLUS_INFO ( logger , " First pass on " < < filename < < " shows " < < firstPass . numberOfNonzeroEntries < < " NonZeros. " ) ;
// If first pass returned zero, the file format was wrong.
if ( firstPass . numberOfNonzeroEntries = = 0 ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : empty or erroneous file format. " ) ;
throw storm : : exceptions : : WrongFormatException ( ) ;
}
// Perform second pass.
// Skip the format hint if it is there.
buf = trimWhitespaces ( buf ) ;
if ( buf [ 0 ] ! = ' 0 ' ) {
buf = storm : : parser : : forwardToNextLine ( buf , lineEndings ) ;
}
// Read next transition.
row = checked_strtol ( buf , & buf ) ;
col = checked_strtol ( buf , & buf ) ;
val = checked_strtod ( buf , & buf ) ;
// The reward matrix should match the size of the transition matrix.
if ( firstPass . highestStateIndex + 1 > rewardMatrixInformation . rowCount | | firstPass . highestStateIndex + 1 > rewardMatrixInformation . columnCount ) {
LOG4CPLUS_ERROR ( logger , " Reward matrix has more rows or columns than transition matrix. " ) ;
throw storm : : exceptions : : WrongFormatException ( ) < < " Reward matrix has more rows or columns than transition matrix. " ;
} else {
// If we found the right number of states or less, we set it to the number of states represented by the transition matrix.
firstPass . highestStateIndex = rewardMatrixInformation . rowCount - 1 ;
}
resultMatrix . addNextValue ( row , col , val ) ;
buf = trimWhitespaces ( buf ) ;
}
} else {
while ( buf [ 0 ] ! = ' \0 ' ) {
// Read next transition.
row = checked_strtol ( buf , & buf ) ;
col = checked_strtol ( buf , & buf ) ;
val = checked_strtod ( buf , & buf ) ;
// Read probability of this transition.
// Check, if the value is a probability, i.e. if it is between 0 and 1.
if ( ( val < 0.0 ) | | ( val > 1.0 ) ) {
LOG4CPLUS_ERROR ( logger , " Expected a positive probability but got \" " < < val < < " \" . " ) ;
throw storm : : exceptions : : WrongFormatException ( ) ;
}
// Test if we moved to a new row.
// Handle all incomplete or skipped rows.
if ( lastRow ! = row ) {
if ( ! rowHadDiagonalEntry ) {
if ( insertDiagonalEntriesIfMissing ) {
resultMatrix . addNextValue ( lastRow , lastRow , storm : : utility : : constantZero < double > ( ) ) ;
LOG4CPLUS_DEBUG ( logger , " While parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. Inserted a 0-transition. (1) " ) ;
} else {
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. " ) ;
}
// No increment for lastRow.
rowHadDiagonalEntry = true ;
}
for ( uint_fast64_t skippedRow = lastRow + 1 ; skippedRow < row ; + + skippedRow ) {
hadDeadlocks = true ;
if ( fixDeadlocks ) {
resultMatrix . addNextValue ( skippedRow , skippedRow , storm : : utility : : constantOne < double > ( ) ) ;
rowHadDiagonalEntry = true ;
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < skippedRow < < " has no outgoing transitions. A self-loop was inserted. " ) ;
} else {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : state " < < skippedRow < < " has no outgoing transitions. " ) ;
// Before throwing the appropriate exception we will give notice of all deadlock states.
}
}
lastRow = row ;
rowHadDiagonalEntry = false ;
}
// Creating matrix builder here.
// The number of non-zero elements is computed by firstPass().
// The contents are inserted during the readout of the file, below.
// The actual matrix will be build once all contents are inserted.
storm : : storage : : SparseMatrixBuilder < double > resultMatrix ( firstPass . highestStateIndex + 1 , firstPass . highestStateIndex + 1 , firstPass . numberOfNonzeroEntries ) ;
if ( col = = row ) {
rowHadDiagonalEntry = true ;
}
uint_fast64_t row , col ;
double val ;
if ( col > row & & ! rowHadDiagonalEntry ) {
if ( insertDiagonalEntriesIfMissing ) {
resultMatrix . addNextValue ( row , row , storm : : utility : : constantZero < double > ( ) ) ;
LOG4CPLUS_DEBUG ( logger , " While parsing " < < filename < < " : state " < < row < < " has no transition to itself. Inserted a 0-transition. (2) " ) ;
} else {
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < row < < " has no transition to itself. " ) ;
}
rowHadDiagonalEntry = true ;
}
// Read all transitions from file. Note that we assume that the
// transitions are listed in canonical order, otherwise this will not
// work, i.e. the values in the matrix will be at wrong places.
while ( buf [ 0 ] ! = ' \0 ' ) {
resultMatrix . addNextValue ( row , col , val ) ;
buf = trimWhitespaces ( buf ) ;
}
// Read next transition.
row = checked_strtol ( buf , & buf ) ;
col = checked_strtol ( buf , & buf ) ;
val = checked_strtod ( buf , & buf ) ;
if ( ! rowHadDiagonalEntry ) {
if ( insertDiagonalEntriesIfMissing ) {
resultMatrix . addNextValue ( lastRow , lastRow , storm : : utility : : constantZero < double > ( ) ) ;
LOG4CPLUS_DEBUG ( logger , " While parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. Inserted a 0-transition. (3) " ) ;
} else {
LOG4CPLUS_WARN ( logger , " Warning while parsing " < < filename < < " : state " < < lastRow < < " has no transition to itself. " ) ;
}
}
resultMatrix . addNextValue ( row , col , val ) ;
buf = trimWhitespaces ( buf ) ;
}
// If we encountered deadlock and did not fix them, now is the time to throw the exception.
if ( ! fixDeadlocks & & hadDeadlocks ) throw storm : : exceptions : : WrongFormatException ( ) < < " Some of the nodes had deadlocks. You can use --fixDeadlocks to insert self-loops on the fly. " ;
}
return resultMatrix . build ( ) ;
// Finally, build the actual matrix and return it.
return resultMatrix . build ( ) ;
}
} // namespace parser