Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DeterministicSparseTransitionParser.cpp
Go to the documentation of this file.
2
3#include <clocale>
4#include <string>
5
13
14namespace storm {
15namespace parser {
16
17using namespace storm::utility::cstring;
18
19template<typename ValueType>
21 std::string const& filename, ExplicitModelParserOptions const& options) {
23 return DeterministicSparseTransitionParser<ValueType>::parse(filename, false, emptyMatrix, options);
24}
25
26template<typename ValueType>
27template<typename MatrixValueType>
29 std::string const& filename, storm::storage::SparseMatrix<MatrixValueType> const& transitionMatrix) {
30 return DeterministicSparseTransitionParser<ValueType>::parse(filename, true, transitionMatrix);
31}
32
33template<typename ValueType>
34template<typename MatrixValueType>
35storm::storage::SparseMatrix<ValueType> DeterministicSparseTransitionParser<ValueType>::parse(
36 std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& transitionMatrix,
37 ExplicitModelParserOptions const& options) {
38 // Enforce locale where decimal point is '.'.
39 setlocale(LC_NUMERIC, "C");
40
41 // Open file.
42 MappedFile file(filename.c_str());
43 char const* buf = file.getData();
44
45 // Perform first pass, i.e. count entries that are not zero.
47 DeterministicSparseTransitionParser<ValueType>::firstPass(file.getData(), !isRewardFile);
48
49 STORM_LOG_TRACE("First pass on " << filename << " shows " << firstPass.numberOfNonzeroEntries << " non-zeros.");
50
51 // If first pass returned zero, the file format was wrong.
52 STORM_LOG_THROW(firstPass.numberOfNonzeroEntries > 0, storm::exceptions::WrongFormatException,
53 "Error while parsing " << filename << ": empty or erroneous file format.");
54
55 // Perform second pass.
56
57 // Skip the format hint if it is there.
58 buf = trimWhitespaces(buf);
59 if (buf[0] < '0' || buf[0] > '9') {
60 buf = forwardToLineEnd(buf);
61 buf = trimWhitespaces(buf);
62 }
63
64 if (isRewardFile) {
65 // The reward matrix should match the size of the transition matrix.
66 if (firstPass.highestStateIndex + 1 > transitionMatrix.getRowCount() || firstPass.highestStateIndex + 1 > transitionMatrix.getColumnCount()) {
67 STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Reward matrix has more rows or columns than transition matrix.");
68 } else {
69 // If we found the right number of states or less, we set it to the number of states represented by the transition matrix.
70 firstPass.highestStateIndex = transitionMatrix.getRowCount() - 1;
71 }
72 }
73
74 // Creating matrix builder here.
75 // The actual matrix will be build once all contents are inserted.
76 storm::storage::SparseMatrixBuilder<ValueType> resultMatrix(firstPass.highestStateIndex + 1, firstPass.highestStateIndex + 1,
77 firstPass.numberOfNonzeroEntries);
78
79 uint_fast64_t row, col, lastRow = 0;
80 double val;
81 bool fixDeadlocks = options.fixDeadlocks;
82 bool hadDeadlocks = false;
83
84 // Read all transitions from file. Note that we assume that the
85 // transitions are listed in canonical order, otherwise this will not
86 // work, i.e. the values in the matrix will be at wrong places.
87
88 // Different parsing routines for transition systems and transition rewards.
89 if (isRewardFile) {
90 while (buf[0] != '\0') {
91 // Read next transition.
92 row = checked_strtol(buf, &buf);
93 col = checked_strtol(buf, &buf);
94 val = checked_strtod(buf, &buf);
95
96 resultMatrix.addNextValue(row, col, val);
97 buf = trimWhitespaces(buf);
98 }
99 } else {
100 // Read first row and add self-loops if necessary.
101 char const* tmp;
102 row = checked_strtol(buf, &tmp);
103
104 if (row > 0) {
105 for (uint_fast64_t skippedRow = 0; skippedRow < row; ++skippedRow) {
106 hadDeadlocks = true;
107 if (fixDeadlocks) {
108 resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<ValueType>());
109 STORM_LOG_WARN("Warning while parsing " << filename << ": state " << skippedRow
110 << " has no outgoing transitions. A self-loop was inserted.");
111 } else {
112 STORM_LOG_ERROR("Error while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions.");
113 // Before throwing the appropriate exception we will give notice of all deadlock states.
114 }
115 }
116 }
117
118 while (buf[0] != '\0') {
119 // Read next transition.
120 row = checked_strtol(buf, &buf);
121 col = checked_strtol(buf, &buf);
122 val = checked_strtod(buf, &buf);
123
124 // Test if we moved to a new row.
125 // Handle all incomplete or skipped rows.
126 if (lastRow != row) {
127 for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
128 hadDeadlocks = true;
129 if (fixDeadlocks) {
130 resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<ValueType>());
131 STORM_LOG_INFO("Warning while parsing " << filename << ": state " << skippedRow
132 << " has no outgoing transitions. A self-loop was inserted.");
133 } else {
134 STORM_LOG_ERROR("Error while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions.");
135 // Before throwing the appropriate exception we will give notice of all deadlock states.
136 }
137 }
138 lastRow = row;
139 }
140
141 resultMatrix.addNextValue(row, col, val);
142 buf = trimWhitespaces(buf);
143 }
144
145 // If we encountered deadlock and did not fix them, now is the time to throw the exception.
146 STORM_LOG_THROW(fixDeadlocks || !hadDeadlocks, storm::exceptions::WrongFormatException, "Some of the states do not have outgoing transitions.");
147 }
148
149 // Finally, build the actual matrix, test and return it.
150 storm::storage::SparseMatrix<ValueType> result = resultMatrix.build();
151
152 // Since we cannot check if each transition for which there is a reward in the reward file also exists in the transition matrix during parsing, we have to
153 // do it afterwards.
154 STORM_LOG_THROW(!isRewardFile || result.isSubmatrixOf(transitionMatrix), storm::exceptions::WrongFormatException,
155 "There are rewards for non existent transitions given in the reward file.");
156
157 return result;
158}
159
160template<typename ValueType>
161typename DeterministicSparseTransitionParser<ValueType>::FirstPassResult DeterministicSparseTransitionParser<ValueType>::firstPass(
162 char const* buf, bool reserveDiagonalElements) {
164
165 // Skip the format hint if it is there.
166 buf = trimWhitespaces(buf);
167 if (buf[0] < '0' || buf[0] > '9') {
168 buf = forwardToLineEnd(buf);
169 buf = trimWhitespaces(buf);
170 }
171
172 // Check all transitions for non-zero diagonal entries and deadlock states.
173 uint_fast64_t row, col, lastRow = 0, lastCol = -1;
174
175 // Read first row and reserve space for self-loops if necessary.
176 char const* tmp;
177 row = checked_strtol(buf, &tmp);
178 if (row > 0 && reserveDiagonalElements) {
179 for (uint_fast64_t skippedRow = 0; skippedRow < row; ++skippedRow) {
180 ++result.numberOfNonzeroEntries;
181 }
182 }
183
184 while (buf[0] != '\0') {
185 // Read the transition.
186 row = checked_strtol(buf, &buf);
187 col = checked_strtol(buf, &buf);
188 // The actual read value is not needed here.
189 checked_strtod(buf, &buf);
190
191 if (lastRow != row && reserveDiagonalElements) {
192 // Compensate for missing rows.
193 for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
194 ++result.numberOfNonzeroEntries;
195 }
196 }
197
198 // Check if a higher state id was found.
199 if (row > result.highestStateIndex) {
200 result.highestStateIndex = row;
201 }
202 if (col > result.highestStateIndex) {
203 result.highestStateIndex = col;
204 }
205
206 ++result.numberOfNonzeroEntries;
207
208 // Have we already seen this transition?
209 STORM_LOG_THROW(row != lastRow || col != lastCol, storm::exceptions::InvalidArgumentException,
210 "The same transition (" << row << ", " << col << ") is given twice.");
211
212 lastRow = row;
213 lastCol = col;
214
215 buf = trimWhitespaces(buf);
216 }
217
218 if (reserveDiagonalElements) {
219 for (uint_fast64_t skippedRow = (uint_fast64_t)(lastRow + 1); skippedRow <= result.highestStateIndex; ++skippedRow) {
220 ++result.numberOfNonzeroEntries;
221 }
222 }
223
224 return result;
225}
226
229 std::string const& filename, storm::storage::SparseMatrix<double> const& transitionMatrix);
230template storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser<double>::parse(std::string const& filename, bool isRewardFile,
231 storm::storage::SparseMatrix<double> const& transitionMatrix,
232 ExplicitModelParserOptions const& options);
233
235
236template storm::storage::SparseMatrix<storm::Interval> DeterministicSparseTransitionParser<storm::Interval>::parseDeterministicTransitionRewards(
237 std::string const& filename, storm::storage::SparseMatrix<double> const& transitionMatrix);
238template storm::storage::SparseMatrix<storm::Interval> DeterministicSparseTransitionParser<storm::Interval>::parse(
239 std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<double> const& transitionMatrix, ExplicitModelParserOptions const& options);
240} // namespace parser
241} // namespace storm
This class can be used to parse a file containing either transitions or transition rewards of a deter...
static storm::storage::SparseMatrix< ValueType > parseDeterministicTransitions(std::string const &filename, ExplicitModelParserOptions const &options=ExplicitModelParserOptions())
Load a deterministic transition system from file and create a sparse adjacency matrix whose entries r...
static storm::storage::SparseMatrix< ValueType > parseDeterministicTransitionRewards(std::string const &filename, storm::storage::SparseMatrix< MatrixValueType > const &transitionMatrix)
Load the transition rewards for a deterministic transition system from file and create a sparse adjac...
Opens a file and maps it to memory providing a char* containing the file content.
Definition MappedFile.h:21
A class that holds a possibly non-square matrix in the compressed row storage format.
bool isSubmatrixOf(SparseMatrix< OtherValueType > const &matrix) const
Checks if the current matrix is a submatrix of the given matrix, where a matrix A is called a submatr...
index_type getColumnCount() const
Returns the number of columns of the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
#define STORM_LOG_INFO(message)
Definition logging.h:27
#define STORM_LOG_WARN(message)
Definition logging.h:28
#define STORM_LOG_TRACE(message)
Definition logging.h:15
#define STORM_LOG_ERROR(message)
Definition logging.h:29
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:28
Contains all file parsers and helper classes.
char const * forwardToLineEnd(char const *buffer)
Encapsulates the usage of function @strcspn to forward to the end of the line (next char is the newli...
Definition cstring.cpp:72
double checked_strtod(char const *str, char const **end)
Calls strtod() internally and checks if the new pointer is different from the original one,...
Definition cstring.cpp:36
uint_fast64_t checked_strtol(char const *str, char const **end)
Calls strtol() internally and checks if the new pointer is different from the original one,...
Definition cstring.cpp:21
char const * trimWhitespaces(char const *buf)
Skips spaces, tabs, newlines and carriage returns.
Definition cstring.cpp:62
ValueType one()
Definition constants.cpp:19
A structure representing the result of the first pass of this parser.
uint_fast64_t highestStateIndex
The highest state index that appears in the model.
uint_fast64_t numberOfNonzeroEntries
The total number of non-zero entries of the model.