@ -12,6 +12,7 @@
# include "src/parser/MappedFile.h"
# include "src/parser/MappedFile.h"
# include "src/settings/Settings.h"
# include "src/settings/Settings.h"
# include "src/exceptions/FileIoException.h"
# include "src/exceptions/FileIoException.h"
# include "src/exceptions/OutOfRangeException.h"
# include "src/exceptions/WrongFormatException.h"
# include "src/exceptions/WrongFormatException.h"
# include "src/utility/cstring.h"
# include "src/utility/cstring.h"
@ -44,7 +45,7 @@ namespace storm {
if ( ! MappedFile : : fileExistsAndIsReadable ( filename . c_str ( ) ) ) {
if ( ! MappedFile : : fileExistsAndIsReadable ( filename . c_str ( ) ) ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : File does not exist or is not readable. " ) ;
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : File does not exist or is not readable. " ) ;
throw storm : : exceptions : : Wrong Format Exception( ) ;
throw storm : : exceptions : : FileI oException ( ) < < " Error while parsing " < < filename < < " : File does not exist or is not readable. " ;
}
}
// Open file.
// Open file.
@ -57,7 +58,7 @@ namespace storm {
// If first pass returned zero, the file format was wrong.
// If first pass returned zero, the file format was wrong.
if ( firstPass . numberOfNonzeroEntries = = 0 ) {
if ( firstPass . numberOfNonzeroEntries = = 0 ) {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : erroneous file format. " ) ;
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : erroneous file format. " ) ;
throw storm : : exceptions : : WrongFormatException ( ) ;
throw storm : : exceptions : : WrongFormatException ( ) < < " Error while parsing " < < filename < < " : erroneous file format. " ;
}
}
// Perform second pass.
// Perform second pass.
@ -73,16 +74,18 @@ namespace storm {
// The reward matrix should match the size of the transition matrix.
// The reward matrix should match the size of the transition matrix.
if ( firstPass . choices > modelInformation . transitionMatrix . getRowCount ( ) | | ( uint_fast64_t ) ( firstPass . highestStateIndex + 1 ) > modelInformation . transitionMatrix . getColumnCount ( ) ) {
if ( firstPass . choices > modelInformation . transitionMatrix . getRowCount ( ) | | ( uint_fast64_t ) ( firstPass . highestStateIndex + 1 ) > modelInformation . transitionMatrix . getColumnCount ( ) ) {
LOG4CPLUS_ERROR ( logger , " Reward matrix size exceeds transition matrix size. " ) ;
LOG4CPLUS_ERROR ( logger , " Reward matrix size exceeds transition matrix size. " ) ;
throw storm : : exceptions : : WrongFormat Exception( ) < < " Reward matrix size exceeds transition matrix size. " ;
throw storm : : exceptions : : OutOfRange Exception( ) < < " Reward matrix size exceeds transition matrix size. " ;
} else if ( firstPass . choices ! = modelInformation . transitionMatrix . getRowCount ( ) ) {
} else if ( firstPass . choices ! = modelInformation . transitionMatrix . getRowCount ( ) ) {
LOG4CPLUS_ERROR ( logger , " Reward matrix row count does not match transition matrix row count. " ) ;
LOG4CPLUS_ERROR ( logger , " Reward matrix row count does not match transition matrix row count. " ) ;
throw storm : : exceptions : : WrongFormatException ( ) < < " Reward matrix row count does not match transition matrix row count. " ;
throw storm : : exceptions : : OutOfRangeException ( ) < < " Reward matrix row count does not match transition matrix row count. " ;
} else if ( firstPass . numberOfNonzeroEntries > modelInformation . transitionMatrix . getEntryCount ( ) ) {
LOG4CPLUS_ERROR ( logger , " The reward matrix has more entries than the transition matrix. There must be a reward for a non existent transition " ) ;
throw storm : : exceptions : : OutOfRangeException ( ) < < " The reward matrix has more entries than the transition matrix. " ;
} else {
} else {
firstPass . highestStateIndex = modelInformation . transitionMatrix . getColumnCount ( ) - 1 ;
firstPass . highestStateIndex = modelInformation . transitionMatrix . getColumnCount ( ) - 1 ;
}
}
}
}
// Create the matrix builder.
// Create the matrix builder.
// The matrix to be build should have as many columns as we have nodes and as many rows as we have choices.
// The matrix to be build should have as many columns as we have nodes and as many rows as we have choices.
// Those two values, as well as the number of nonzero elements, was been calculated in the first run.
// Those two values, as well as the number of nonzero elements, was been calculated in the first run.
@ -93,7 +96,7 @@ namespace storm {
std : : vector < uint_fast64_t > rowMapping ( firstPass . highestStateIndex + 2 , 0 ) ;
std : : vector < uint_fast64_t > rowMapping ( firstPass . highestStateIndex + 2 , 0 ) ;
// Initialize variables for the parsing run.
// Initialize variables for the parsing run.
uint_fast64_t source = 0 , target = 0 , lasts ource = 0 , choice = 0 , lastc hoice = 0 , curRow = 0 ;
uint_fast64_t source = 0 , target = 0 , lastS ource = 0 , choice = 0 , lastC hoice = 0 , curRow = 0 ;
double val = 0.0 ;
double val = 0.0 ;
bool fixDeadlocks = storm : : settings : : Settings : : getInstance ( ) - > isSet ( " fixDeadlocks " ) ;
bool fixDeadlocks = storm : : settings : : Settings : : getInstance ( ) - > isSet ( " fixDeadlocks " ) ;
bool hadDeadlocks = false ;
bool hadDeadlocks = false ;
@ -108,33 +111,33 @@ namespace storm {
if ( isRewardFile ) {
if ( isRewardFile ) {
// If we have switched the source state, we possibly need to insert the rows of the last
// If we have switched the source state, we possibly need to insert the rows of the last
// source state.
// source state.
if ( source ! = lasts ource ) {
curRow + = ( ( modelInformation . rowMapping ) [ lasts ource + 1 ] - ( modelInformation . rowMapping ) [ lasts ource ] ) - ( lastc hoice + 1 ) ;
if ( source ! = lastS ource ) {
curRow + = ( ( modelInformation . rowMapping ) [ lastS ource + 1 ] - ( modelInformation . rowMapping ) [ lastS ource ] ) - ( lastC hoice + 1 ) ;
}
}
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
// choices.
for ( uint_fast64_t i = lasts ource + 1 ; i < source ; + + i ) {
for ( uint_fast64_t i = lastS ource + 1 ; i < source ; + + i ) {
curRow + = ( ( modelInformation . rowMapping ) [ i + 1 ] - ( modelInformation . rowMapping ) [ i ] ) ;
curRow + = ( ( modelInformation . rowMapping ) [ i + 1 ] - ( modelInformation . rowMapping ) [ i ] ) ;
}
}
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// for them
// for them
if ( source ! = lasts ource ) {
if ( source ! = lastS ource ) {
curRow + = choice + 1 ;
curRow + = choice + 1 ;
} else if ( choice ! = lastc hoice ) {
curRow + = choice - lastc hoice ;
} else if ( choice ! = lastC hoice ) {
curRow + = choice - lastC hoice ;
}
}
} else {
} else {
// Increase line count if we have either finished reading the transitions of a certain state
// Increase line count if we have either finished reading the transitions of a certain state
// or we have finished reading one nondeterministic choice of a state.
// or we have finished reading one nondeterministic choice of a state.
if ( ( source ! = lasts ource | | choice ! = lastc hoice ) ) {
if ( ( source ! = lastS ource | | choice ! = lastC hoice ) ) {
+ + curRow ;
+ + curRow ;
}
}
// Check if we have skipped any source node, i.e. if any node has no
// Check if we have skipped any source node, i.e. if any node has no
// outgoing transitions. If so, insert a self-loop.
// outgoing transitions. If so, insert a self-loop.
// Also add self-loops to rowMapping.
// Also add self-loops to rowMapping.
for ( uint_fast64_t node = lasts ource + 1 ; node < source ; node + + ) {
for ( uint_fast64_t node = lastS ource + 1 ; node < source ; node + + ) {
hadDeadlocks = true ;
hadDeadlocks = true ;
if ( fixDeadlocks ) {
if ( fixDeadlocks ) {
rowMapping . at ( node ) = curRow ;
rowMapping . at ( node ) = curRow ;
@ -145,7 +148,7 @@ namespace storm {
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : node " < < node < < " has no outgoing transitions. " ) ;
LOG4CPLUS_ERROR ( logger , " Error while parsing " < < filename < < " : node " < < node < < " has no outgoing transitions. " ) ;
}
}
}
}
if ( source ! = lasts ource ) {
if ( source ! = lastS ource ) {
// Add this source to rowMapping, if this is the first choice we encounter for this state.
// Add this source to rowMapping, if this is the first choice we encounter for this state.
rowMapping . at ( source ) = curRow ;
rowMapping . at ( source ) = curRow ;
}
}
@ -156,8 +159,8 @@ namespace storm {
val = checked_strtod ( buf , & buf ) ;
val = checked_strtod ( buf , & buf ) ;
matrixBuilder . addNextValue ( curRow , target , val ) ;
matrixBuilder . addNextValue ( curRow , target , val ) ;
lasts ource = source ;
lastc hoice = choice ;
lastS ource = source ;
lastC hoice = choice ;
// Proceed to beginning of next line in file and next row in matrix.
// Proceed to beginning of next line in file and next row in matrix.
buf = forwardToLineEnd ( buf ) ;
buf = forwardToLineEnd ( buf ) ;
@ -165,7 +168,7 @@ namespace storm {
buf = trimWhitespaces ( buf ) ;
buf = trimWhitespaces ( buf ) ;
}
}
for ( uint_fast64_t node = lasts ource + 1 ; node < = firstPass . highestStateIndex + 1 ; node + + ) {
for ( uint_fast64_t node = lastS ource + 1 ; node < = firstPass . highestStateIndex + 1 ; node + + ) {
rowMapping . at ( node ) = curRow + 1 ;
rowMapping . at ( node ) = curRow + 1 ;
}
}
@ -186,7 +189,7 @@ namespace storm {
}
}
// Read all transitions.
// Read all transitions.
uint_fast64_t source = 0 , target = 0 , choice = 0 , lastc hoice = 0 , lasts ource = 0 ;
uint_fast64_t source = 0 , target = 0 , choice = 0 , lastC hoice = 0 , lastS ource = 0 ;
double val = 0.0 ;
double val = 0.0 ;
NondeterministicSparseTransitionParser : : FirstPassResult result ;
NondeterministicSparseTransitionParser : : FirstPassResult result ;
@ -201,6 +204,11 @@ namespace storm {
// Read the name of the nondeterministic choice.
// Read the name of the nondeterministic choice.
choice = checked_strtol ( buf , & buf ) ;
choice = checked_strtol ( buf , & buf ) ;
if ( source < lastSource ) {
LOG4CPLUS_ERROR ( logger , " The current source state " < < source < < " is smaller than the last one " < < lastSource < < " . " ) ;
throw storm : : exceptions : : InvalidArgumentException ( ) < < " The current source state " < < source < < " is smaller than the last one " < < lastSource < < " . " ;
}
// Check if we encountered a state index that is bigger than all previously seen.
// Check if we encountered a state index that is bigger than all previously seen.
if ( source > result . highestStateIndex ) {
if ( source > result . highestStateIndex ) {
result . highestStateIndex = source ;
result . highestStateIndex = source ;
@ -209,32 +217,34 @@ namespace storm {
if ( isRewardFile ) {
if ( isRewardFile ) {
// If we have switched the source state, we possibly need to insert rows for skipped choices of the last
// If we have switched the source state, we possibly need to insert rows for skipped choices of the last
// source state.
// source state.
if ( source ! = lasts ource ) {
if ( source ! = lastS ource ) {
// number of choices skipped = number of choices of last state - number of choices read
// number of choices skipped = number of choices of last state - number of choices read
result . choices + = ( ( modelInformation . rowMapping ) [ lasts ource + 1 ] - ( modelInformation . rowMapping ) [ lasts ource ] ) - ( lastc hoice + 1 ) ;
result . choices + = ( ( modelInformation . rowMapping ) [ lastS ource + 1 ] - ( modelInformation . rowMapping ) [ lastS ource ] ) - ( lastC hoice + 1 ) ;
}
}
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
// choices.
for ( uint_fast64_t i = lasts ource + 1 ; i < source ; + + i ) {
for ( uint_fast64_t i = lastS ource + 1 ; i < source ; + + i ) {
result . choices + = ( ( modelInformation . rowMapping ) [ i + 1 ] - ( modelInformation . rowMapping ) [ i ] ) ;
result . choices + = ( ( modelInformation . rowMapping ) [ i + 1 ] - ( modelInformation . rowMapping ) [ i ] ) ;
}
}
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// for them.
// for them.
if ( source ! = lasts ource ) {
if ( source ! = lastS ource ) {
result . choices + = choice + 1 ;
result . choices + = choice + 1 ;
} else if ( choice ! = lastc hoice ) {
result . choices + = choice - lastc hoice ;
} else if ( choice ! = lastC hoice ) {
result . choices + = choice - lastC hoice ;
}
}
} else {
} else {
// If we have skipped some states, we need to reserve the space for the self-loop insertion
// If we have skipped some states, we need to reserve the space for the self-loop insertion
// in the second pass.
// in the second pass.
if ( source > lastsource + 1 ) {
result . numberOfNonzeroEntries + = source - lastsource - 1 ;
result . choices + = source - lastsource - 1 ;
} else if ( source ! = lastsource | | choice ! = lastchoice ) {
if ( source > lastSource + 1 ) {
result . numberOfNonzeroEntries + = source - lastSource - 1 ;
result . choices + = source - lastSource - 1 ;
}
if ( source ! = lastSource | | choice ! = lastChoice ) {
// If we have switched the source state or the nondeterministic choice, we need to
// If we have switched the source state or the nondeterministic choice, we need to
// reserve one row more.
// reserve one row more.
+ + result . choices ;
+ + result . choices ;
@ -250,14 +260,19 @@ namespace storm {
// Read value and check whether it's positive.
// Read value and check whether it's positive.
val = checked_strtod ( buf , & buf ) ;
val = checked_strtod ( buf , & buf ) ;
if ( ( val < 0.0 ) | | ( val > 1.0 ) ) {
if ( ! isRewardFile & & ( val < 0.0 | | val > 1.0 ) ) {
LOG4CPLUS_ERROR ( logger , " Expected a positive probability but got \" " < < std : : string ( buf , 0 , 16 ) < < " \" . " ) ;
LOG4CPLUS_ERROR ( logger , " Expected a positive probability but got \" " < < std : : string ( buf , 0 , 16 ) < < " \" . " ) ;
NondeterministicSparseTransitionParser : : FirstPassResult nullResult ;
NondeterministicSparseTransitionParser : : FirstPassResult nullResult ;
return nullResult ;
return nullResult ;
}
}
else if ( val < 0.0 ) {
LOG4CPLUS_ERROR ( logger , " Expected a positive reward value but got \" " < < std : : string ( buf , 0 , 16 ) < < " \" . " ) ;
NondeterministicSparseTransitionParser : : FirstPassResult nullResult ;
return nullResult ;
}
lastchoice = choice ;
lastsource = source ;
lastC hoice = choice ;
lastS ource = source ;
// Increase number of non-zero values.
// Increase number of non-zero values.
result . numberOfNonzeroEntries + + ;
result . numberOfNonzeroEntries + + ;
@ -271,11 +286,11 @@ namespace storm {
if ( isRewardFile ) {
if ( isRewardFile ) {
// If not all rows were filled for the last state, we need to insert them.
// If not all rows were filled for the last state, we need to insert them.
result . choices + = ( ( modelInformation . rowMapping ) [ lasts ource + 1 ] - ( modelInformation . rowMapping ) [ lasts ource ] ) - ( lastc hoice + 1 ) ;
result . choices + = ( ( modelInformation . rowMapping ) [ lastS ource + 1 ] - ( modelInformation . rowMapping ) [ lastS ource ] ) - ( lastC hoice + 1 ) ;
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
// choices.
for ( uint_fast64_t i = lasts ource + 1 ; i < modelInformation . rowMapping . size ( ) - 1 ; + + i ) {
for ( uint_fast64_t i = lastS ource + 1 ; i < modelInformation . rowMapping . size ( ) - 1 ; + + i ) {
result . choices + = ( ( modelInformation . rowMapping ) [ i + 1 ] - ( modelInformation . rowMapping ) [ i ] ) ;
result . choices + = ( ( modelInformation . rowMapping ) [ i + 1 ] - ( modelInformation . rowMapping ) [ i ] ) ;
}
}
}
}